简体   繁体   中英

Change state in parent component from child, then pass that state as property and change state in child component

I have a parent component with two child components. A button click action should change state parent component and that should affect both of child components.

This is my parent component:

export default class SearchView extends React.Component {
  // attributes
  state = {
    loading: false
  }

  //
  constructor(props){
    super(props)
  }

  // get list of items
  getItems(){
    this.setState({loading:true})
    axios.get('/path_to_data').then( response => {
      this.setState({items:response.data, loading: false})
    }).catch(err=>{console.log(err)})
  }

  render(){
    return (
      <div>
        <SearchForm
          getItems={this.getItems.bind(this)}
          loading={this.state.loading}
        />
      { this.state.items ?  <ItemCards items={this.state.items} /> : "No data"}
      </div>
    )
  }//render

}//class

This is my component where click event happens:

export default class SearchForm extends React.Component {
  // attributes
  state = {
    loading: this.props.loading
  }

  // render
  render(){
    return (
      <Segment inverted color="yellow">
        <Grid columns="2">
          <Grid.Column>
          </Grid.Column>
          <Grid.Column>
            <Button
              loading={this.state.loading}
              disabled={this.state.loading}
              color="black"
              onClick={this.props.getItems}
            >
              Search
            </Button>
          </Grid.Column>
        </Grid>
      </Segment>
    )
  }//render

}//class SearchForm

and this is other child component:

export default class ItemCards extends React.Component {

  // constructor
  constructor(props){
    super(props)
  }
  // state
  state = {
    items: this.props.items
  }
  ...

The problem is that when a button is clicked I would expect that change in state object of loading attribute would be changed, and so would property passed into this same child component where event was triggered. And then I would expect this child component to detect that state of parent was changed and that property as well, and then it would change it's own state and UI would render loading attribute on element until response comes (when response comes, loading is removed).

Why doesn't this code work as expected? How do I fix it?

In this example, the <Button> component shouldn't have any state, and just use props instead.

So try rewriting to:

<Button
   loading={this.props.loading} 
   disabled={this.props.loading}
   color="black"
   onClick={this.props.getHotels}>

The reason is that in react, you don't pass state from one component to another. State is something that is contained within an individual component. A good pattern is for the parent component to hold the state, and communicate with children via props.

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