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

Javascript 使用React JS显示/隐藏(子)列表项,javascript,css,reactjs,Javascript,Css,Reactjs,在React JS组件中,我使用一个数组中的JS映射函数呈现一个项目列表(食谱),该函数是从应用程序父组件传入的。每个项目都有一个子列表(成分),再次使用map函数呈现 我想要的是,当你点击菜谱标题时,显示/隐藏配料的子列表。我在标题上使用了onClick函数,将CSS设置为显示none或block,但出现以下错误: 未捕获的TypeError:无法读取未定义的属性“openRecipe” 这是我的密码: var App = React.createClass({ getInitialS

在React JS组件中,我使用一个数组中的JS映射函数呈现一个项目列表(食谱),该函数是从应用程序父组件传入的。每个项目都有一个子列表(成分),再次使用map函数呈现

我想要的是,当你点击菜谱标题时,显示/隐藏配料的子列表。我在标题上使用了onClick函数,将CSS设置为显示none或block,但出现以下错误:

未捕获的TypeError:无法读取未定义的属性“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'));
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)}>.....