Javad Sameri
Javad Sameri

Reputation: 1319

save react component and load later

I have react component in react native app and this will return Smth like this:

constructor(){
    ...
    this.Comp1 = <Component1 ..... >
    this.Comp2 = <Component2 ..... >
}
render(){
    let Show = null
    if(X) Show = this.Comp1
    else Show = this.Comp1
    return(
        {X}
        )
    }

and both of my Components have an API request inside it ,

so my problem is when condition is changed and this toggle between Components , each time the Components sent a request to to that API to get same result ,

I wanna know how to save constructed Component which they wont send request each time

Upvotes: 2

Views: 3443

Answers (2)

Amr Labib
Amr Labib

Reputation: 4083

One of the ways do that is to handle the hide and show inside each of the child component comp1 and comp2

So you will still render both comp1 and comp2 from the parent component but you will pass a prop to each one of them to tell them if they need to show or hide inner content, if show then render the correct component content, else just render empty <Text></Text>

This means both child components exist in parent, and they never get removed, but you control which one should show its own content by the parent component.

So your data is fetched only once.


Check Working example in react js: https://codesandbox.io/s/84p302ryp9
If you checked the console log you will find that fetching is done once for comp1 and comp2.


Also check the same example in react native below:

class Parent extends Component {
  constructor(props)
  {
    super(props);
    this.state={
      show1 : true //by default comp1 will show
    }
  }

  toggleChild= ()=>{
    this.setState({
      show1 : !this.state.show1
    });
  }

  render(){
    return (
      <View >
        <Button onPress={this.toggleChild} title="Toggle Child" />
        <Comp1 show={this.state.show1} />
        <Comp2 show={!this.state.show1} />
      </View>
    )
  }
}

Comp1:

class Comp1 extends Component
{
  constructor(props) {
    super(props);
    this.state={
      myData : ""

    }
  }

  componentWillMount(){
    console.log("fetching data comp1 once");
    this.setState({
      myData : "comp 1"
    })
  }


  render(){
    return (
      this.props.show ? <Text>Actual implementation of Comp1</Text> : <Text></Text>
    )
  }
}

Comp2:

class Comp2 extends Component {
  constructor(props) {
    super(props);
    this.state = {
      myData2: ""

    }
  }

  componentWillMount() {
    console.log("fetching data in comp2 once");
    this.setState({
      myData2: "comp 2"
    });
  }


  render() {
    return (
      this.props.show ? <Text>Actual implementation of Comp2</Text> : <Text></Text>
    )
  }
}

Upvotes: 3

Slawa Eremin
Slawa Eremin

Reputation: 5415

I think, you should move all your logic to the main component (fetching and saving data, so you component1 and component2 are simple dumb components. In component1 and component2 you can check "does component have some data?", if there isn't any data, you can trigger request for that data in parent component.

Full working example here: https://codesandbox.io/s/7m8qvwr760

class Articles extends React.Component {
  componentDidMount() {
    const { fetchData, data } = this.props;

    if (data && data.length) return;

    fetchData && fetchData();
  }

  render() {
    const { data } = this.props;

    return (
      <div>
        {data && data.map((item, key) => <div key={key}>{item.title}</div>)}
      </div>
    )
  }
}

class App extends React.Component{
  constructor(props){
    super(props);

    this.state = {
      news: [],
      articles: [],
      isNews: false
    }
  }

  fetchArticles = () => {
    const self = this;  

    setTimeout( () => {
      console.log('articles requested');

      self.setState({
        articles: [{title: 'article 1'}, {title: 'articles 2'}]
      })
    }, 1000)
  }

  fetchNews = () => {
    const self = this;

    setTimeout(() => {
      console.log('news requested');

      self.setState({
        news: [{ title: 'news 1' }, { title: 'news 2' }]
      })
    }, 1000)
  }

  handleToggle = (e) => {
    e.preventDefault();
    this.setState({
      isNews: !this.state.isNews
    })
  }

  render(){
    const { news, articles, isNews} = this.state;

    return (
      <div>
        <a href="#" onClick={this.handleToggle}>Toggle</a>

        {isNews? (
          <News data={news} fetchData={this.fetchNews} />
        ): (
           <Articles data={articles} fetchData={this.fetchArticles} />
        )}

      </div>

    )
  }
}

Upvotes: 2

Related Questions