Home > Blockchain >  How to force a tag to full-width in React-Native-Render-Html?
How to force a tag to full-width in React-Native-Render-Html?

Time:12-04

We have a custom renderer for span tags but I can't find any way to force the span to full-width. I tried wrapping the custom renderer in a View as well as applying all the usual React-Native styles without luck.

Given input HTML like below

<span>Hello</span><span>Goodbye</span>

How can we render it as below?

Hello     
goodbye 

Currently it renders inline like:

hello goodbye


The custom renderer looks like this:


const renderers = {
  span: RenderedSpan,
};

const RenderedSpan = props => {
  return (
      <Text>
        Some hardcoded text
      </Text>
  );
};

I figured I'd finally found a solution for the issue when I came across an example

That inspired me to try this code to set the contentModel to block:

(still no dice)

const customHTMLElementModels = {
  span: defaultHTMLElementModels.span.extend({
    contentModel: HTMLContentModel.block,
  }),
};

CodePudding user response:

React Native Capabilities

React Native has roughly two display algorithms: flex, and text-inline. Any element which has a Text parent will be displayed with the text-inline algorithm, and all other elements will be displayed with the flex algorithm. The former severely limits the set of styles which will be supported, this is what you are stumbling on.

Elements inside text-inline will have the following styles ignored:

  • Margins
  • Percent-widths
  • All flex rules

I suggest you play with a snippet like the one below to have a gist:

import React from 'react';
import {SafeAreaView, useWindowDimensions, View, Text} from 'react-native';

export default function App() {
  const {width} = useWindowDimensions();
  return (
    <SafeAreaView style={{flex: 1}}>
      <Text>
        Hello world!
        <View style={{ /* play with padding, margins, flex... etc! */ }}>
          <Text>I'm inside a view!</Text>
        </View>
        How are you doing?
      </Text>
    </SafeAreaView>
  );
}

Solution 1: force width

Hence, the only way we could achieve what you are looking for via styles would be to set its width to the passed contentWidth:

import React from 'react';
import {SafeAreaView, useWindowDimensions, View} from 'react-native';
import RenderHTML, {
  CustomTextualRenderer,
  useContentWidth,
} from 'react-native-render-html';

const htmlContent = `
<span>Hello</span><span>Goodbye</span>
`;

const RenderedSpan: CustomTextualRenderer = ({TDefaultRenderer, ...props}) => {
  const width = useContentWidth();

  return (
    <View style={{width}}>
      <TDefaultRenderer {...props} />
    </View>
  );
};

const renderers = {
  span: RenderedSpan,
};

export default function App() {
  const {width} = useWindowDimensions();
  return (
    <SafeAreaView style={{flex: 1}}>
      <RenderHTML
        renderers={renderers}
        source={{html: htmlContent}}
        contentWidth={width}
      />
    </SafeAreaView>
  );
}

LINK TO SNACK

Solution 2: use Block content model

You suggested setting the span content model to block and with the snippet you provided, it works great:

import React from 'react';
import {SafeAreaView, useWindowDimensions, View} from 'react-native';
import RenderHTML, {
  defaultHTMLElementModels,
  HTMLContentModel,
} from 'react-native-render-html';

const htmlContent = `
<span>Hello</span><span>Goodbye</span>
`;

const customHTMLElementModels = {
  span: defaultHTMLElementModels.span.extend({
    contentModel: HTMLContentModel.block,
  }),
};

export default function App() {
  const {width} = useWindowDimensions();
  return (
    <SafeAreaView style={{flex: 1}}>
      <RenderHTML source={{html: htmlContent}} contentWidth={width} customHTMLElementModels={customHTMLElementModels} />
    </SafeAreaView>
  );
}

The block content model will force the render engine to guarantee rendered span elements won't have any Text ascendants, thus securing a flex column display. LINK TO SNACK

CodePudding user response:

Did you try something like this :

    import * as React from 'react';
    import { Text, View, StyleSheet } from 'react-native';

    export default function App() {

        const renderers = {
          span: RenderedSpan,
        };

        const RenderedSpan = props => {

          const styles = StyleSheet.create({
            container: {
              flex: 1,
              backgroundColor:"#ff0000"
            },
          });
                    
          return (
            <View style={styles.container}>
              <Text>Some hardcoded text</Text>
            </View>
          );
        };

        return <RenderedSpan/>;
    }
  • Related