基本上是React的新手,我对如何在组件之间正确传递状态感到困惑。我发现了一个类似的问题React – the right way to pass form element state to sibling/parent elements? 但是我想知道你是否可以给我一个特定的答案来解释下面的代码。
目前,该应用程序的结构包括:
App
SearchBar
和RecipesList
目标是在我的Meteor集合上进行异步搜索,并仅显示与搜索词匹配的recipes
。
现在,我只是在我的Meteor系列中展示所有食谱。
我创建了一个名为SearchBar
的有状态组件,它将输入值保存为this.state.term
。我的想法是将状态传递给RecipesList
,但我不确定这是否正确。或者,我让App
处理状态并将其传递给孩子。我相信这是一种非常常见的情况,你是怎么做到的?
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 );
答案 0 :(得分: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>
)
}
}
App
组件处理状态,然后通过props.searchQuery向RecipesList
提供搜索术语作为道具传递给子项。
searchInputChange
处理程序作为道具传递给SearchBar
。
SearchBar
export default const SearchBar = ({value, onChange}) => (
<div className=" container-fluid search-bar">
<input value={value} onChange={onChange}/>
Value: {value}
</div>
)
由于SearchBar
委托状态到父组件,我们可以使用无状态反应组件,因为我们只需要来自props的信息来呈现它。
一般来说,最好让logical
或stateful
或controller
组件处理状态和逻辑,然后该组件将状态和方法传递给{{1 }}或presentational
组件,用于处理用户看到和与之交互的内容。
答案 1 :(得分:0)
将状态term
定义到App组件中。
还要编写handleInput函数并将其作为porps
handleInput(val) {
this.setState({
term: val,
});
}
当输入搜索栏中的某些内容(onKeyUp)时,添加侦听器handleInput。
同时创建<RecipesList searchQuery={this.state.term}/>
现在在渲染功能RecipesList中过滤掉你想要从列表中显示的食谱