Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use internal default renderers logic in custom renderers #424

Closed
wulaizi opened this issue Nov 5, 2020 · 7 comments
Closed

Use internal default renderers logic in custom renderers #424

wulaizi opened this issue Nov 5, 2020 · 7 comments
Labels
enhancement An enhancement is a change that is not a feature. is:missing template This issue does not comply with our contribution guidelines.

Comments

@wulaizi
Copy link

wulaizi commented Nov 5, 2020

Can renderers return a page element? For example, I just want to get attributes through renderers, but don’t want to change the element, but this method must require an element to be returned. If it is a picture, I return Image, which will cause the picture to be blurred (because I have no width and height when I return, I can only get it through Image.getSize Will make the picture blurry) So I don’t want to do any processing, I just want to return a webpage element img, how to operate it as it is

@wulaizi wulaizi added the enhancement An enhancement is a change that is not a feature. label Nov 5, 2020
@wulaizi
Copy link
Author

wulaizi commented Nov 5, 2020

renderers={{
img: (htmlAttribs, children, convertedCSSStyles, passProps) => {
let imageSrc = htmlAttribs?.name || htmlAttribs?.src
let newImageUrl = RegHelper.HandleImage(imageSrc)
return React.createElement('img',{
src: newImageUrl
})
}
}}

@jsamr
Copy link
Collaborator

jsamr commented Nov 5, 2020

@wulaizi If I understand you well, you would like to change the DOM node attributes? If that is the case, you could use alterNode :-)

@jsamr
Copy link
Collaborator

jsamr commented Nov 5, 2020

const alterNode = (domNode) => {
  if (domNode.tagName === "img") {
    const htmlAttribs = domNode.attribs;
    let imageSrc = htmlAttribs?.name || htmlAttribs?.src;
    let newImageUrl = RegHelper.HandleImage(imageSrc);
    domNode.attribs = { ...htmlAttribs, src: newImageUrl };
  }
  return domNode;
}

And then pass alterNode to HTML component!

@wulaizi
Copy link
Author

wulaizi commented Nov 6, 2020

常量 alterNode  =  (れ) =>  {
  如果 (れ。的tagName  ===  “IMG”  {
    常量 htmlAttribs  = れ。属性; 
     imageSrc  =  htmlAttribs吗?。名称 ||  htmlAttribs?。src ; 
     newImageUrl  =  RegHelper 。HandleImage (imageSrc ; 
    domNode 。属性 =  { ... htmlAttribs  src:newImageUrl  } ; 
  } 
  return  domNode ; 
}

然后传递alterNode给HTML组件!

Thank you very much for your answer, very nice, I have a requirement here, before the picture is loaded, use htmlAttribs?.src (preview) After loading, use htmlAttribs?.name, when you click on the picture, give the picture address to "react- native-image-zoom-viewer "may need a method to trigger an image click event

@wulaizi
Copy link
Author

wulaizi commented Nov 6, 2020

常量 alterNode  =  (れ) =>  {
  如果 (れ。的tagName  ===  “IMG”  {
    常量 htmlAttribs  = れ。属性; 
     imageSrc  =  htmlAttribs吗?。名称 ||  htmlAttribs?。src ; 
     newImageUrl  =  RegHelper 。HandleImage (imageSrc ; 
    domNode 。属性 =  { ... htmlAttribs  src:newImageUrl  } ; 
  } 
  return  domNode ; 
}

然后传递alterNode给HTML组件!

Thank you very much for your answer, very nice, I have a requirement here, before the picture is loaded, use htmlAttribs?.src (preview) After loading, use htmlAttribs?.name, when you click on the picture, give the picture address to "react- native-image-zoom-viewer "may need a method to trigger an image click event

I chose “renderers” before because he can upload a "TouchableOpacity" trigger event, but when the renderers return the picture, because my picture is a high-definition large picture, using Image will cause blur, so I gave up using HTML img because the effect is very good, but I don’t know how to go. Trigger event method

@jsamr
Copy link
Collaborator

jsamr commented Nov 6, 2020

常量 alterNode  =  (れ) =>  {
  如果 (れ。的tagName  ===  “IMG”  {
    常量 htmlAttribs  = れ。属性; 
     imageSrc  =  htmlAttribs吗?。名称 ||  htmlAttribs?。src ; 
     newImageUrl  =  RegHelper 。HandleImage (imageSrc ; 
    domNode 。属性 =  { ... htmlAttribs  src:newImageUrl  } ; 
  } 
  return  domNode ; 
}

然后传递alterNode给HTML组件!

Thank you very much for your answer, very nice, I have a requirement here, before the picture is loaded, use htmlAttribs?.src (preview) After loading, use htmlAttribs?.name, when you click on the picture, give the picture address to "react- native-image-zoom-viewer "may need a method to trigger an image click event

I understand your requirement. This is unfortunately not yet possible, but it is an interesting use case for the next version. I am thinking of an API that would look like this:

const renderers = {
  img: (...params) => {
    return (
      <ImageRenderer {...params}>
        {({ isLoading, width, height }) => {
          return; /** Whatever you need to return! */
        }}
      </ImageRenderer>
    );
  },
};

PS: If you are confused with the syntax, see react patterns, render prop

@jsamr jsamr changed the title Can renderers return a page element? Use internal default renderers logic in custom renderers Nov 10, 2020
@jsamr jsamr added the is:missing template This issue does not comply with our contribution guidelines. label Nov 11, 2020
jsamr added a commit that referenced this issue Jan 15, 2021
Each default renderer (img, a, ul, ol) has now a corresponding XElement
(where X should be replaced with the element tag name) and
useXElementProps available to customize the rendering logic.

resolves #424
jsamr added a commit that referenced this issue Feb 10, 2021
This is a complete refactoring as much as a feature of the image
renderer. Thanks to this new hook, you can very easily create custom
image renderers which still preserves the rich scaling behavior of the
internal component. This hook will return three different states:

- 'loading', when the scaled image dimensions have not been retrieved
   yet;
- 'success', when the scaled image dimensions are available;
- 'error', when the image could not be cached.

During the 'loading' phase, this hooks uses `Image.getSize` from react
native to pre-fetch the image and access its natural (intrinsic) dimensions.

fix #424
jsamr added a commit that referenced this issue Feb 11, 2021
This is a complete refactoring as much as a feature of the image
renderer. Thanks to this new hook, you can very easily create custom
image renderers which still preserves the rich scaling behavior of the
internal component. This hook will return three different states:

- 'loading', when the natural image dimensions have not been retrieved
   yet;
- 'success', when the concrete image dimensions are available;
- 'error', when the image could not be cached.

During the 'loading' phase, this hooks uses `Image.getSize` from react
native to pre-fetch the image and access its natural (intrinsic) dimensions.
See https://drafts.csswg.org/css-images/#sizing-terms for detailed
definitions relating to "concrete", "specified" and "natural" dimensions.

fix #424
@jsamr
Copy link
Collaborator

jsamr commented Feb 11, 2021

@wulaizi You can now reuse the img component internal logic in the Foundry pre-release (6.0.0-alpha-15). See #430 for more information on how to try out this pre-release. Below is an example:

import React from 'react';
import {
  IMGElementContainer,
  IMGElementContentError,
  IMGElementContentSuccess,
  IMGElementContentLoading,
  useIMGElementProps,
  useIMGElementState,
  defaultHTMLElementModels
} from 'react-native-render-html';

const CustomImageRenderer = function ({ onPress, source, ...props }) {
  const imgElementProps = useIMGElementProps(props);
  const alteredProps = {
    ...imgElementProps,
    source: {
      uri: RegHelper.HandleImage(source.uri)
    }
  };
  const state = useIMGElementState(alteredProps);
  let content = false;
  if (state.type === 'success') {
    content = React.createElement(IMGElementContentSuccess, state);
  } else if (state.type === 'loading') {
    content = React.createElement(IMGElementContentLoading, state);
  } else {
    content = React.createElement(IMGElementContentError, state);
  }
  return (
    <IMGElementContainer onPress={onPress} style={state.containerStyle}>
      {content}
    </IMGElementContainer>
  );
};

CustomImageRenderer.model = defaultHTMLElementModels.img;

export default CustomImageRenderer;

You can therefore chose what to render depending on the internal state of this component. The fields accessible in the state will depend on state.type.

jsamr added a commit that referenced this issue Jun 4, 2021
This is a complete refactoring as much as a feature of the image
renderer. Thanks to this new hook, you can very easily create custom
image renderers which still preserves the rich scaling behavior of the
internal component. This hook will return three different states:

- 'loading', when the natural image dimensions have not been retrieved
   yet;
- 'success', when the concrete image dimensions are available;
- 'error', when the image could not be cached.

During the 'loading' phase, this hooks uses `Image.getSize` from react
native to pre-fetch the image and access its natural (intrinsic) dimensions.
See https://drafts.csswg.org/css-images/#sizing-terms for detailed
definitions relating to "concrete", "specified" and "natural" dimensions.

fix #424
@jsamr jsamr closed this as completed in 213fcd7 Jun 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement An enhancement is a change that is not a feature. is:missing template This issue does not comply with our contribution guidelines.
Projects
None yet
Development

No branches or pull requests

2 participants