Search code examples
reactjsloopscomponentssiblings

React — Passing data between siblings and iterating it


I have two questions, the first is about passing data between components and the second is about the component hierarchy.

Right now, in the Data component I am trying to set the name property and pass it to a ListItem component that should iterate based on the API request. I tried many things without success. What am I doing wrong? Does the data needs to be iterated when setting the new state? Am I passing it correctly?

Basic pseudocode

  • Read data from API
  • Set data to the component state
  • Create siblings components based on data stored
  • Render components

The second question is about the hierarchy of the components. I keep reading around the web that the data request should be setup at the top and separated. Having this in place, the other components would feed from this data and execute. Finally, the App component would render all this components accordingly. From the example below, am I going to the right track? Was I correct to creating a component specific for data request or should this be done in the App component?

I understand these questions might be basic but it is something that I am really struggling to understand and I would appreciate if someone can help me understand or point me to a basic example that I can digest.

Thank you in advance. (Sorry, I had more than two questions.)

class App extends React.Component {
  render() {
    return (
      <ul>
        <ListItem name={this.state.name} />
      </ul>
    )
  }
}


class Data extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      name: '',
      requestFailed: false,
    }
  }

  componentDidMount() { // Executes after mouting


    fetch('https://api.tfl.gov.uk/BikePoint')
    .then((response) => {
      return response.json()
    }).then((d) =>  {
      console.log('parsed json', d[0].commonName)
      this.setState({
            name: d.commonName
      });
    }).catch(function(ex) {
      console.log('parsing failed', ex)
      this.setState({
          requestFailed: true
        })
    })
  }

  render() {

    if(this.state.requestFailed) return <p>Request failed.</p>
    if(!this.state.name) return <p>Loading</p>

    const namesList = names.map(function(name, index){
      return <ListItem key={index} name={this.state.name} />
    })

    return  <ul>{ namesList }</ul>
  }
}

class ListItem extends React.Component {
  render() {
    return <li> { this.props.name } </li>
  }
}

ReactDOM.render(<App />, document.getElementById('app'));

CodePen


Solution

  • Where to start -

    First, your App component needs to render Data component. React works in the way that parent element always renders children elements and what is not rendered doesn't exist.

    Then, you need to remap response to names, if that is what you wanted to do - I am not sure.

    In render method, you want to take name out of mapping function, not from state. I also removed name state, you really want to keep names instead of one name. There is a lot of small thing I had to adjust to make it work, so I will just post working code pen here, so you can see what needed to be done.

    https://codepen.io/anon/pen/eEmqxX?editors=0010