Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - Passing State between siblings?

Basically new to React, I'm a bit confused on how to properly pass states between components. I found a similar question already React – the right way to pass form element state to sibling/parent elements? but I wonder if you can give me a specific answer for the code below.

Currently the structure of the app includes:

  • parent component - App
  • 2 childs: SearchBar and RecipesList

The goal is to make an async search on my Meteor collection and display only the recipes that match the search term.

Right now, I'm just showing all the recipes in my Meteor collection. I've created a stateful component named SearchBar which holds the input value as this.state.term. The idea is to pass the state to RecipesList but I'm not sure if it's the right thing to do. Alternatively I'd let App deal with the state and passing it to the childs. I believe this is a very common scenario, how do you do it?

App

class App extends Component {

render( ) {
    return (
        <div>
            <Navbar/>
            <SearchBar/>
            <RecipesList/>
        </div>
    );
}
}

SearchBar

export default class SearchBar extends Component {

constructor( props ) {
    super( props );

    this.state = {
        term: ''
    };
}

onInputChange( term ) {
    this.setState({ term });
}

render( ) {
    return (
        <div className=" container-fluid search-bar">
            <input value={this.state.term} onChange={event => this.onInputChange(event.target.value.substr( 0, 50 ))}/>
            Value: {this.state.term}
        </div>
    );
}

}

RecipesList

const PER_CLICK = 5;

class RecipesList extends Component {

componentWillMount( ) {
    this.click = 1;
}

handleButtonClick( ) {
    Meteor.subscribe('recipes', PER_CLICK * ( this.click + 1 ));
    this.click++;
}

renderList( ) {
    return this.props.recipes.map(recipe => {
        return (
            <div key={recipe._id} className="thumbnail">
                <img src={recipe.image} alt="recipes snapshot"/>
                <div className="caption">
                    <h2 className="text-center">{recipe.recipeName}</h2>
                </div>
            </div>
        );
    });
}

render( ) {
    return (
        <ul className="list-group">
            {this.renderList( )}
            <div className="container-fluid">
                <button onClick={this.handleButtonClick.bind( this )} className="btn btn-default">More</button>
            </div>
        </ul>
    );
}
}

// Create Container and subscribe to `recipes` collection
export default createContainer( ( ) => {
Meteor.subscribe( 'recipes', PER_CLICK );
return {recipes: Recipes.find({ }).fetch( )};
}, RecipesList );
like image 882
frankydep Avatar asked Oct 30 '22 15:10

frankydep


1 Answers

App

class App extends Component {
  constructor(props, ctx){
    super(props, ctx)

    this.state = {
      searchQuery: ''
    }

    this.searchInputChange = this.searchInputChange.bind(this)
  }

  searchInputChange(event) {
    this.setState({
      searchQuery: event.target.value.substr( 0, 50 )
    })
  }

  render( ) {
    const { searchQuery } = this.state
    return (
      <div>
        <Navbar/>
        <SearchBar onChange={this.searchInputChange} value={searchQuery}/>
        <RecipesList searchQuery={searchQuery}/>
      </div>
    )
  }
}

The App component takes care of the state and this is then passed down to the children as props the seach term is available to RecipesList through props.searchQuery.

The searchInputChange handler is passed down to the SearchBar as props.

SearchBar

export default const SearchBar = ({value, onChange}) => (
  <div className=" container-fluid search-bar">
    <input value={value} onChange={onChange}/>
    Value: {value}
  </div>
)

Since the SearchBar delegated state to the parent component, we can use a stateless react component as we only need information from the props to render it.

In general it is always best to have a logical or stateful or controller component take care of state and the logic, this component then passes down state and methods to presentational or view components which take care of what the user sees and interacts with.

like image 76
Jesse McIntosh Avatar answered Nov 15 '22 05:11

Jesse McIntosh