向上传递数据的问题React树更改DOM

时间:2017-10-24 01:45:56

标签: javascript jquery reactjs react-redux bootstrap-4

**这可能是一个简单的答案,我是React的新手,谢谢你的帮助! **

背景故事

我有一个隐藏在主app内部的模态(bootstrap4),其内部有一个表单,在渲染时,表单会根据所选配方中的信息填写(稍后会详细介绍)。 / p>

配方存储在本地并且this.state.currentRecipe我知道正在选择哪个配方(它用作索引,默认设置为0)。

因此,使用this.state.currentRecipe作为索引,第一个渲染自然会放入第一个食谱的信息。

我试图通过创建一个函数并将其传递给子组件来解决这个问题。食谱卡中包含所有信息和编辑按钮。因此,当食谱卡全部由.map()呈现时,我传入它们的索引和传递的函数,以便更改this.state.currentRecipe的状态,并使用具有以下形式的表单重新呈现DOM新信息。

出了什么问题

然而,当我点击编辑按钮时会弹出模态,第一个配方总是。它甚至会更改this.state.currentRecipe,但DOM不会使用正确的配方信息重新渲染。

当我点击“编辑”时,如何根据我所处的食谱卡更新表单的信息?按钮?(每张卡中都有一个按钮)。

(即使它确实如此,它会再次隐藏模态吗?)

以下是repo https://github.com/JeremyWeisener/React-Recipe-box/tree/master/src/components

的组件文件夹的链接

如果以下代码没有足够的信息

以下是我认为重要的4个主要文件的内部(清理了一下并放在这里让生活更轻松)

app.js

import React, { Component } from 'react';
import RecipeCard from './recipe-card';
import RecipeBook from './recipe-book';
import AddRecipe from './add-recipe';
import RecipeEditer from './edit-recipe';

export default class App extends Component {

    constructor(props) {
        super(props);
        this.state = {
            currentRecipe: 0,
            recipes: JSON.parse(localStorage.getItem('cookBook')),
            updateKey: 0,
            counter: 0
        }
    }

    changeRecipe = (arg) => {

        this.setState({currentRecipe:arg});

    }


  render() {

    return (

    <div>
        <div>
          <RecipeBook changeRecipe={this.changeRecipe.bind(this)} recipes={this.state.recipes} />         

        </div>

        <div id="popUps">
            <AddRecipe />
            <RecipeEditer index={this.state.currentRecipe} forglory={this.state} />
        </div>

        <div id="editPopup">

        </div>
    </div>
    );
  }
}

配方-book.js

import React from 'react';
import RecipeCard from './recipe-card';

const RecipeBook = (props) => {

        var changeRecipe = props.changeRecipe;

        console.log(props);

        const DisplayRecipes = props.recipes.map((recipe, index) => {

            return <RecipeCard index={index} key={index+1} recipe={recipe} changeRecipe={changeRecipe.bind(this)} />

        })



    return (

        <div id="accordion" role="tablist" aria-multiselectable="true">

            {DisplayRecipes}

                  <div>
                    <button className="btn btn-primary" type="button" data-toggle="modal" data-target="#addRecipe"> Add Recipe </button>
                  </div>

        </div>
    );

}

export default RecipeBook;

配方-card.js

import React from 'react';
import Ingredients from './recipe-ingredients';
import Steps from './recipe-steps';
import RecipeEditer from './edit-recipe';

const RecipeCard = (props) => {

    const changeRecipe = props.changeRecipe;

    return (    
        <div>
        {/*Card Start*/}
        <div className="recipe card">
            {/*Header*/}
            <div className="card-header" role="tab" id={`heading${props.index}`}>
              <h5 className="mb-0">
                <a data-toggle="collapse" data-parent="#accordion" href={`#collapse${props.index}`} aria-expanded="true" aria-controls={`collapse${props.index}`}>
                {props.recipe.title}
                </a>
              </h5>
            </div>
            {/*End Header*/}

            {/*Collapse Div*/}
                <div id={`collapse${props.index}`} className="collapse" role="tabpanel" aria-labelledby={`heading${props.index}`}>
                {/*Card IMG*/}
                <img className="card-img-top" src="./img/Fried Chik'n-edit1.jpg" />
                {/*Card Block*/}
                <div className="card-block">
                    <p className="card-text">

                    </p>
                        {/* Ingredients */}
                    <h3>Ingredients</h3>
                    <Ingredients parts={props.recipe.ingredients} />
                        {/* Steps */}
                    <h3>Steps</h3>
                    <Steps levels={props.recipe.steps} />

                    <a href="#" className="btn btn-primary">Print Recipe</a>

                    {/*Edit Button is here*/}
                    <button onClick={() => {changeRecipe(props.index)}} className="btn btn-success" type="button" data-toggle="modal" data-target="#editRecipe"> Edit Recipe </button>
                    {/*Edit Button is here*/}

                    <a href="#" className="btn btn-danger">Delete Recipe</a>
                </div>
                {/*End Card Block*/}
            </div>
            {/*End Collapsable*/}
        </div>
        {/*End Card*/}
    </div>

    );

}


export default RecipeCard;

编辑recipe.js

import React from 'react';


const RecipeEditer = (props) => {

    var index = props.index;

    var cookBook = JSON.parse(localStorage.getItem("cookBook"));
    var editMe = cookBook[props.forglory.currentRecipe];

    const UpdateRecipe = () => {

        var formData = $('#recipeEditer').serializeArray();


        var newRecipe = {};

            newRecipe.title         = formData[0]['value'];
            newRecipe.image         = formData[1]['value'];
            newRecipe.ingredients   = formData[2]['value'].split(',');
            newRecipe.steps         = formData[3]['value'].split(',');

        cookBook[index] = newRecipe; 

        localStorage.setItem("cookBook", JSON.stringify(cookBook));


    }


    return (

        <div className="modal fade" id="editRecipe" tabIndex="-1" role="dialog" aria-labelledby="editRecipeLabel" aria-hidden="false">
          <div className="modal-dialog" role="document">
            <div className="modal-content">
              <div className="modal-header">
              {/* Title */}
                <h5 className="modal-title" id="exampleModalLabel">
                    Edit Recipe
                </h5>
                <button type="button" className="close" data-dismiss="modal" aria-label="Close">
                  <span aria-hidden="false">&times;</span>
                </button>
              </div>
              <div className="modal-body">
                <form id="recipeEditer" name="editRecipe">

                    <label htmlFor="name"><h4>Name</h4></label>
                    <input id="name" className="form-control" name="title" type="text" defaultValue={editMe.title} />

                    <label htmlFor="image"><h4>Image</h4></label>
                    <input id="image" className="form-control" name="image" type="text" defaultValue={editMe.image} />

                    <label htmlFor="ingredients"><h4>Ingredients</h4></label>
                    <textarea id="ingredients" className="form-control" name="ingredients" rows="4" cols="48" defaultValue={editMe.ingredients}></textarea>
                    <label htmlFor="steps"><h4>Steps</h4></label><br/>
                    <textarea id="steps" className="form-control" name="steps" cols="48" rows="4" defaultValue={editMe.steps} ></textarea>

                </form>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-secondary" data-dismiss="modal">Close</button>

                {/*Submit Button*/}
                <button onClick={UpdateRecipe} type="button" className="btn btn-success" data-dismiss="modal">Change Recipe</button>
                {/*Submit Button*/}
              </div>
            </div>
          </div>
        </div>
    );
}


export default RecipeEditer;

非常感谢你,如果你看了一眼,如果有更多的信息可以提供帮助,请不要犹豫!

1 个答案:

答案 0 :(得分:0)

您将changeRecipe绑定到this中的recipe-book.js,从而将其上下文设置为RecipeBook

尝试更改

<RecipeCard index={index} key={index+1} recipe={recipe} changeRecipe={changeRecipe.bind(this)} />

<RecipeCard index={index} key={index+1} recipe={recipe} changeRecipe={changeRecipe} />

您甚至不必在app.js中使用绑定,因为changeRecipe被定义为箭头功能。