React - 在兄弟姐妹之间传递状态?

fra*_*dep 5 javascript meteor reactjs

基本上是 React 的新手,我对如何在组件之间正确传递状态有点困惑。我已经在React 中发现了一个类似的问题——将表单元素状态传递给兄弟/父元素的正确方法? 但我想知道你是否可以给我下面代码的具体答案。

目前应用程序的结构包括:

  • 父组件 - App
  • 2个孩子:SearchBarRecipesList

目标是对我的 Meteor 集合进行异步搜索,并仅显示recipes与搜索词匹配的内容。

现在,我只是展示了我的 Meteor 收藏中的所有食谱。我创建了一个名为的有状态组件SearchBar,它将输入值保存为this.state.term. 这个想法是将状态传递给,RecipesList但我不确定这是否正确。或者,我会让App处理状态并将其传递给孩子。我相信这是一个很常见的场景,你是怎么做的?

App

class App extends Component {

render( ) {
    return (
        <div>
            <Navbar/>
            <SearchBar/>
            <RecipesList/>
        </div>
    );
}
}
Run Code Online (Sandbox Code Playgroud)

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>
    );
}

}
Run Code Online (Sandbox Code Playgroud)

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 );
Run Code Online (Sandbox Code Playgroud)

小智 2

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>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

App组件负责处理状态,然后将其作为可RecipesList通过 props.searchQuery 使用的 props 传递给子级。

处理程序searchInputChange被传递给SearchBaras 属性。

SearchBar

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

由于将SearchBar状态委托给父组件,我们可以使用无状态的 React 组件,因为我们只需要 props 中的信息来渲染它。

一般来说,最好让一个logicalstatefulcontroller组件负责状态和逻辑,然后该组件将状态和方法传递给presentationalview组件,该组件负责用户所看到的内容并与之交互。