gpt4 book ai didi

javascript - 使用 React JS 显示/隐藏(子)列表项

转载 作者:行者123 更新时间:2023-11-29 21:12:25 25 4
gpt4 key购买 nike

在 React JS 组件中,我正在渲染元素列表(食谱),使用数组中的 JS 映射函数,从 App 父组件传入。每个元素都有一个子列表(成分),再次使用 map 函数呈现。

我想要的是在您单击食谱标题时显示/隐藏成分的子列表。我在标题上使用 onClick 函数将 CSS 设置为不显示或阻止显示,但我收到以下错误:

未捕获类型错误:无法读取未定义的属性“openRecipe”

这是我的代码:

var App = React.createClass({


getInitialState(){

return{

showModal:false,


recipeKeys: [ ],

recipes: [ ]

}


},

addRecipeKey: function(recipe){


var allKeys = this.state.recipeKeys.slice();

var allRecipes = this.state.recipes.slice();

allKeys.push(recipe.name);

allRecipes.push(recipe);

localStorage.setObj("recipeKeys", allKeys);


this.setState({recipeKeys: allKeys, recipes: allRecipes}, function(){

console.log(this.state);


});


},

componentDidMount: function(){

var dummyRecipes = [

{
"name": "Pizza",

"ingredients": ["Dough", "Tomato", "Cheese"]

},

{
"name": "Sushi",

"ingredients": ["Rice", "Seaweed", "Tuna"]

}

]


if(localStorage.getItem("recipeKeys") === null){

localStorage.setObj("recipeKeys", ["Pizza", "Sushi"]);

dummyRecipes.forEach(function(item){

localStorage.setObj(item.name, item);

});

this.setState({recipeKeys: ["Pizza", "Sushi"], recipes: dummyRecipes}, function(){

console.log(this.state);

});


} else {

var recipeKeys = localStorage.getObj("recipeKeys");

var recipes = [];

recipeKeys.forEach(function(item){

var recipeObject = localStorage.getObj(item);

recipes.push(recipeObject);

});


this.setState({recipeKeys: recipeKeys, recipes: recipes}, function(){

console.log(this.state);

});



}


},


open: function(){


this.setState({showModal:true});

},

close: function(){


this.setState({showModal:false});

},

render: function(){

return(

<div className="container">
<h1>Recipe Box</h1>
<RecipeList recipes = {this.state.recipes} />
<AddRecipeButton openModal = {this.open}/>
<AddRecipe closeModal = {this.close} showModal={this.state.showModal} addRecipeKey = {this.addRecipeKey}/>
</div>

)

}


});

var RecipeList = React.createClass({


openRecipe: function(item){


var listItem = document.getElementById(item);

if(listItem.style.display == "none"){

listItem.style.display = "block";

} else {

listItem.style.display = "none";
}

},

render: function(){

return (

<ul className="list-group">

{this.props.recipes.map(

function(item,index){

return (

<li className="list-group-item" onClick={this.openRecipe(item)}>
<h4>{item.name}</h4>
<h5 className="text-center">Ingredients</h5>
<hr/>
<ul className="list-group" id={index} >
{item.ingredients.map(function(item){

return (
<li className="list-group-item">
<p>{item}</p>
</li>
)

})}
</ul>
</li>

)

}


)


}

</ul>


)


}


});

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

此外,我在这里尝试使用 CSS 方法,但也许有更好的方法来使用 React?

谁能帮帮我?谢谢!

最佳答案

您的问题是您在 map 中丢失了 this 上下文...您需要将 .bind(this) 添加到 map 函数的末尾

{this.props.recipes.map(function(item,index){...}.bind(this))};

我回答了另一个question very similar to this here .如果您可以使用箭头功能,它会自动为您绑定(bind),这是最好的。如果你不能这样做,那么要么使用绑定(bind),要么为你在 map 函数中使用的 this 上下文创建一个影子变量。

现在是清理部分。您需要稍微清理一下代码。

var RecipeList = React.createClass({
getInitialState: function() {
return {display: []};
},
toggleRecipie: function(index){
var inArray = this.state.display.indexOf(index) !== -1;

var newState = [];
if (inArray) { // hiding an item
newState = this.state.display.filter(function(item){return item !== index});
} else { // displaying an item
newState = newState.concat(this.state.display, [index]);
}
this.setState({display: newState});
},
render: function(){
return (
<ul className="list-group">
{this.props.recipes.map(function(item,index){
var inArray = this.state.display.indexOf(index) !== -1;
return (
<li className="list-group-item" onClick={this.toggleRecipie.bind(this, index)}>
<h4>{item.name}</h4>
<h5 className="text-center">Ingredients</h5>
<hr/>
<ul className="list-group" id={index} style={{display: inArray ? 'block' : 'none'}} >
{item.ingredients.map(function(item){
return (
<li className="list-group-item">
<p>{item}</p>
</li>
)
}.bind(this))}
</ul>
</li>
)
}.bind(this))
}
</ul>
)
}
});

这可能有点复杂,您可能不想管理一个索引列表来切换成分 View 。我建议您为您的代码制作组件,这样它更以 react 为中心,并且可以更轻松地切换 View 。

我也将使用 ES6 语法编写此代码,因为您应该使用 ES6。

const RecipieList = (props) => {
return (
<ul className="list-group">
{props.recipes.map( (item,index) => <RecipieItem recipie={item} /> )
</ul>
);
};

class RecipieItem extends React.Component {
constructor(){
super();
this.state = {displayIngredients: false}
}
toggleRecipie = () => {
this.setState({displayIngredients: !this.state.displayIngredients});
}
render() {
return (
<li className="list-group-item" onClick={this.toggleRecipie}>
<h4>{item.name}</h4>
<h5 className="text-center">Ingredients</h5>
<hr/>
<ul className="list-group" style={{display: this.state.displayIngredients ? 'block' : 'none'}} >
{this.props.recipie.ingredients.map( (item) => <IngredientItem ingredient={item} /> )}
</ul>
</li>
);
}
}

const IngredientItem = (props) => {
return (
<li className="list-group-item">
<p>{props.ingredient}</p>
</li>
);
};

关于javascript - 使用 React JS 显示/隐藏(子)列表项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41113702/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com