简体   繁体   中英

React - How to render components inside a function outside of render plus execute same function outside of render?

I have a function outside of render. That function returns (conditionally) a component, that function is beeing triggered not inside render, but inside componentWillReceiveProps (which was necessary due to other facts). My problem is that the function does not end up returning the component and I dont know why. When I call that function inside render, then of it works, but I cant do that as I must call it inside componentWillReceiveProps. Any ideas? Thanks!!

class App extends React.Component {
  componentWillReceiveProps(nextProps) {
    if (nextProps.user != this.props.user) {
      this.getData(nextProps.user)
    }
  }

  getData() {
    if (...) {
      return <Child />
    }
  }

  render() {
    return (
      <div>{this.getData}</div>
    );
  }
}

const Child = () => {
  return <h1>Hello</h1>
}

Create a state called data in the constructor as follows:

constructor(props){
    super(props);
    this.state={data:""};
}

Now, {this.getdata} inside render() with {this.state.data}

Also replace componentWillReceiveProps as follows:

componentWillReceiveProps(nextProps) {
    if (nextProps.user != this.props.user) {
        var newdata = this.getData(nextProps.user)
        this.setState({data:newdata});
    }
}

You can only return JSX data in render and not in the other lifecycle function to render. Also render method is pure so for the same input it returns the same output and hence react is able to rightly optimise on performance for the same by maintaining a virtual dom, so you would just write

class App extends React.Component {
      getData() {
        if (...) {
            return <Child />
        }
      }
      render() {
          return (
              <div>
                {this.getData()}
              </div>
          )
      }
}

const Child = () => {
    return <h1>Hello</h1>
}

and it would have a the same effect, also if you further optimise by using React.PureComponent , so that render is called on when there is a prop change. React.PureComponent implements shouldComponentUpdate with a shallow prop and state comparison.

class App extends React.PureComponent {
      componentWillReceiveProps(nextProps) {
         if (nextProps.user != this.props.user) {
         this.getData(nextProps.user)
         }
      }
      getData() {
        if (...) {
            return <Child />
        }
      }
      render() {
          return (
              <div>
                {this.getData()}
              </div>
          )
      }
}

However to do what you want, you would actually store the date in state of component and then render the data based on state in render method

class App extends React.Component {
      constructor(props) {
         super(props);
         this.state {
             data: this.getData(props)
         }
      }
      componentWillReceiveProps(nextProps) {
         if (nextProps.user != this.props.user) {
            this.getData(nextProps.user)
         }
      }
      getData(props) {
        if (...) {
            const newData;
            // update newData based on receivedProps here
            // store the data in state
            this.setState({data: newData});
        }
        return [];
      }
      render() {
          return (
              <div>
                {this.state.data.map((obj) => return <Child data={obj}/>)}
              </div>
          )
      }
}

Because you can't return children from other hooks than render you will need to keep them in a state:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      someChildren: null
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.user != this.props.user) {
      this.setState({ someChildren: this.getData(nextProps.user) });
    }
  }
  getData() {
    if (...) {
      return <Child />;
    }
    return null
  }
  render() {
    return <div>{this.state.someChildren}</div>;
  }
}

When you component will receive new props, it will re-render automatically, doing like following you should have you component to re-render and being updated:

class App extends React.Component {
  getData: () => {
    if (...) {
      return <Child />
    }
    return null;
  };

  render() {
    return (
      <div>{this.getData()}</div>
    );
  }
}

componentWillReceiveProps is React lifecycle method which is invoked as soon as your React Component receive a prop by the parent. Actions that could be performed in there are for example update the state what you are doing instead is calling a getDate method which is returning a React Component .

A possible implementation could be:

class App extends React.Component {

  getData() {
    const { user } = this.props;
    return user ? <Child /> : <div />
  }
  render() {
      return (
          <div>
            {this.getData()}
          </div>
      )
  }
}

const Child = () => {
  return <h1>Hello</h1>
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM