Javascript 使用React JS显示/隐藏(子)列表项
在React JS组件中,我使用一个数组中的JS映射函数呈现一个项目列表(食谱),该函数是从应用程序父组件传入的。每个项目都有一个子列表(成分),再次使用map函数呈现 我想要的是,当你点击菜谱标题时,显示/隐藏配料的子列表。我在标题上使用了onClick函数,将CSS设置为显示none或block,但出现以下错误: 未捕获的TypeError:无法读取未定义的属性“openRecipe” 这是我的密码:Javascript 使用React JS显示/隐藏(子)列表项,javascript,css,reactjs,Javascript,Css,Reactjs,在React JS组件中,我使用一个数组中的JS映射函数呈现一个项目列表(食谱),该函数是从应用程序父组件传入的。每个项目都有一个子列表(成分),再次使用map函数呈现 我想要的是,当你点击菜谱标题时,显示/隐藏配料的子列表。我在标题上使用了onClick函数,将CSS设置为显示none或block,但出现以下错误: 未捕获的TypeError:无法读取未定义的属性“openRecipe” 这是我的密码: var App = React.createClass({ getInitialS
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'));
var-App=React.createClass({
getInitialState(){
返回{
showModal:错,
recipeKeys:[],
食谱:[]
}
},
addRecipeKey:函数(配方){
var allKeys=this.state.recipeKeys.slice();
var allRecipes=this.state.recipes.slice();
allKeys.push(recipe.name);
所有配方。推送(配方);
setObj(“recipeKeys”,allkey);
this.setState({recipeKeys:allKeys,recipes:allRecipes},function()){
console.log(this.state);
});
},
componentDidMount:function(){
var dummyRecipes=[
{
“名称”:“比萨饼”,
“配料”:[“面团”、“番茄”、“奶酪”]
},
{
“名称”:“寿司”,
“配料”:[“大米”、“海藻”、“金枪鱼”]
}
]
if(localStorage.getItem(“recipeKeys”)==null){
setObj(“recipeKeys”、“Pizza”、“Sushi”);
dummyRecipes.forEach(函数(项){
setObj(item.name,item);
});
this.setState({recipeKeys:[“Pizza”,“Sushi”],recipes:dummyRecipes},function()){
console.log(this.state);
});
}否则{
var recipeKeys=localStorage.getObj(“recipeKeys”);
var配方=[];
recipeKeys.forEach(功能(项目){
var recipeObject=localStorage.getObj(项);
配方。推送(recipeObject);
});
this.setState({recipeKeys:recipeKeys,recipes:recipes},function()){
console.log(this.state);
});
}
},
打开:函数(){
this.setState({showmodel:true});
},
关闭:函数(){
this.setState({showmodel:false});
},
render:function(){
报税表(
配方盒
)
}
});
var RecipeList=React.createClass({
openRecipe:函数(项){
var listItem=document.getElementById(项目);
如果(listItem.style.display==“无”){
listItem.style.display=“block”;
}否则{
listItem.style.display=“无”;
}
},
render:function(){
返回(
{this.props.recipes.map(
功能(项目、索引){
返回(
-
{item.name}
成分
{item.components.map(函数(item)){
返回(
-
{item}
)
})}
)
}
)
}
)
}
});
ReactDOM.render(,document.getElementById('app'));
另外,我试图在这里使用CSS方法,但也许有更好的方法来使用React
有人能帮我吗?谢谢 您的问题是您正在地图中丢失此上下文。。。您需要将
.bind(this)
添加到map函数的末尾
{this.props.recipes.map(function(item,index){...}.bind(this))};
我回答了另一个问题。如果您可以使用箭头函数,它会自动绑定,这是最好的。如果您不能做到这一点,那么可以使用一个bind,或者为您在map函数中使用的this上下文创建一个shadow变量
现在是清理部分。你需要稍微整理一下你的代码
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>
)
}
});
var RecipeList=React.createClass({
getInitialState:函数(){
返回{display:[]};
},
toggleRecipie:函数(索引){
var inArray=this.state.display.indexOf(index)!=-1;
var newState=[];
if(inArray){//隐藏项
newState=this.state.display.filter(函数(项){return item!==index});
}else{//显示项目
newState=newState.concat(this.state.display,[index]);
}
this.setState({display:newState});
},
render:function(){
返回(
{this.props.recipes.map(函数(项,索引){
var inArray=this.state.display.indexOf(index)!=-1;
返回(
-
{item.name}
成分
{item.components.map(函数(item)){
返回(
-
{item}
)
}.bind(this))}
)
}.绑定(本)
}
)
}
});
这可能有点复杂,您可能不想管理一个标记列表来切换成分视图。我建议您为您的代码制作组件,这样它更以反应为中心,并且更容易切换视图
我将用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>
);
};
const RecipieList=(道具)=>{
返回(
{props.recipes.map((项,索引)=>)
);
};
类RecipieItem扩展了React.Component{
构造函数(){
超级();
this.state={displayComponents:false}
}
toggleRecipie=()=>{
此.setState({DisplayComponents:
render: function(){
var self = this;
return (
<ul className="list-group">
{this.props.recipes.map(
function(item,index){
return (
<li className="list-group-item" onClick={self.openRecipe(item)}>.....