我很擅长做出反应并且真的陷入困境。我正在开发一种订购应用程序。人们可以订购产品,并可以选择他们想要的所有成分。我想用每个成分的复选框做这个。 Unfort。我只是不知道如何解决这个问题。另外,我想知道我是否必须在我的组件中使用状态或仅使用变量。
所以我正在通过成分数组进行映射,对于每种成分我都会显示一个复选框来打开/关闭一种成分。所以我的主要问题是,我如何使用这些复选框调整我的对象,如果我需要在我的组件中有一个状态以跟上复选框的最新状态,我将如何将产品设置为我的状态?因为它来自道具。
我尝试过各种各样的事情,例如来自文档:
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
但话又说回来,我怎样才能将产品添加到我的州?此外,这将是不同的,因为成分在对象中,文档中的示例只是值而不是特定对象。
我的组件
import React from 'react';
import { Link } from 'react-router-dom';
class Order extends React.Component {
constructor(props) {
super(props);
}
handleToggle(e) {
//Handle the toggle, set the value of the ingredient to 0 or 1
}
getData(e, product) {
e.preventDefault();
console.log(product)
}
render() {
const product = this.props.products.find((product) => {
return product.id == this.props.match.params.id;
});
return (
<form className="container mx-auto px-4 pt-6" onSubmit={(e) => this.getData(e, product) }>
<Link to={`/${this.props.match.params.category}`} className="mb-4 relative block text-brand hover:text-brand-dark">← Terug naar categorie</Link>
<div className="flex flex-row items-center justify-between bg-white rounded px-8 py-8 shadow-sm mb-4">
<div className="">
<h2 className="text-brand uppercase">{product && product.name}</h2>
<div className="ingre">
<p>
{product && product.ingredients.map((item) => {
return <span className="ing text-grey-dark text-sm" key={item.name}>{item.name}</span>
})}
</p>
</div>
</div>
<div className="">
<h3 className="text-brand text-4xl">€{product && product.price}</h3>
</div>
</div>
<div className="flex flex-wrap mb-4 -mx-2">
{product && product.ingredients.map((item) => {
return (
<div className="w-1/2 mb-4 px-2" key={item.name}>
<div className="flex flex-row items-center justify-between bg-white rounded px-8 py-8 shadow-sm">
<div>
<h3 className="text-grey-dark font-normal text-sm">{item.name}</h3>
</div>
<div>
<input type="checkbox" checked={item.value} name={item} onChange={(e) => this.handleToggle(e)}/>
</div>
</div>
</div>
);
})}
</div>
<button type="submit" className="bg-brand hover:bg-brand-dark text-white font-bold py-4 px-4 rounded">
Order this product
</button>
</form>
);
}
}
export default Order;
产品示例
所以实际上我需要跟踪产品并将成分的值绑定到复选框。如果未选中,则该值必须为0(或为假)。
编辑:
父组件传递道具
// React deps
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
// Custom components
import Navigation from './components/General/Navigation'
// Pages
import Index from './components/Index'
import Category from './components/Category'
import Order from './components/Order'
// Data
import products from './Data'
class App extends Component {
constructor(props) {
super(props);
this.state = {
products: []
}
}
componentWillMount() {
setTimeout(() => {
this.setState({products});
}, 100);
}
render() {
return (
<main className="App font-sans">
<Router>
<div>
<Navigation logo="Jackies" />
<Switch>
<Route exact path="/" component={Index} />
<Route exact path="/:category" render={(props) => <Category {...props} products={this.state.products} />}/>
<Route exact path="/:category/:id" render={(props) => <Order {...props} products={this.state.products} />}/>
</Switch>
</div>
</Router>
</main>
);
}
}
export default App;
答案 0 :(得分:1)
在父级中,您将在onIngredientToggle
道具中传递处理函数:
<Route exact path="/:category/:id" render={(props) => <Order {...props} products={this.state.products} onIngredientToggle={this.handleIngredientToggle} />}/>
然后定义handleIngredientToggle
函数:
function handleIngredientToggle(productId, ingredientIndex, newIngredientValue) {
// basically this goes shallow cloning the objects and arrays up to
// the point it changes the ingredient value property
let products = [...this.state.products];
let modifiedProductIndex = products.findIndex(p => p.id === productId);
let product = {...products[modifiedProductIndex]};
products[modifiedProductIndex] = product;
product.ingredients = [...products[modifiedProductIndex].ingredients];
product.ingredients[ingredientIndex] = {...product.ingredients[ingredientIndex], value: newIngredientValue};
this.setState({products});
}
// If you prefer, the above function can be replaced with:
function handleIngredientToggle(productId, ingredientIndex, newIngredientValue) {
// deep clone products
let products = JSON.parse(JSON.stringify(this.state.products));
// modify just what changed
products.find(p => p.id === productId).ingredients[ingredientIndex].value = newIngredientValue;
this.setState({products});
}
在Order
子项中,您将index
参数添加到map
(您有两个,只需添加到第二个):
{product && product.ingredients.map((item, index) => {
在复选框中将product
和index
传递给handleToggle
函数作为参数:
<input type="checkbox" checked={item.value} name={item} onChange={(e) => this.handleToggle(e, product, index)}/>
然后在函数实现中,您将从父级调用作为prop接收的函数:
handleToggle(e, product, index) {
this.props.onIngredientToggle(product.id, index, e.target.checked);
}
答案 1 :(得分:0)
感谢@acdcjunior打开我疲惫的眼睛,我找到了解决方案
Checkbox html
<input type="checkbox" checked={item.value} name={item} onChange={(e) => this.handleToggle(e, item, product)}/>
子组件上的函数
handleToggle(e, item, product) {
//Get value from checkbox and set it the opposite
let value = e.target.checked ? 1 : 0;
//Pass down the item (ingredient) and parent product and also the value
this.props.toggleIngredient(item, product, value);
}
在父组件上更改状态的功能
toggleIngredient(i, p, v) {
// Get the product from the state
var product = this.state.products.find((product) => {
return product.id == p.id
});
// Filter down the state array to remove the product and get new products array
let products = this.state.products.filter((product) => {
return product != product;
});
// Get the ingredient object
var object = product.ingredients.find((product) => {
return product == i;
});
// Set the value for the ingredient, either true or false (depends on checkbox state)
object.value = v;
// Push the edited product the array of products
products.push(product);
// Set the state with the new products array
this.setState({
products: products
});
}