**这可能是一个简单的答案,我是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
的组件文件夹的链接如果以下代码没有足够的信息
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>
);
}
}
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;
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;
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">×</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;
答案 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
被定义为箭头功能。