我正在构建一个购物车应用程序,我遇到了一个问题,我的所有输入都具有相同的状态值。一切正常,但是当我输入一个输入框时,它在我所有其他输入中都是一样的。
我尝试在输入中添加一个名称字段,并将我的初始状态设置为undefined,并且工作正常,但数字不会通过。
当输入具有相同的状态值时,我们如何处理不同的输入?或者这不可能/愚蠢吗?
class App extends Component {
state = {
items: {
1: {
id: 1, name: 'Yeezys', price: 300, remaining: 5
},
2: {
id: 2, name: 'Github Sweater', price: 50, remaining: 5
},
3: {
id: 3, name: 'Protein Powder', price: 30, remaining: 5
}
},
itemQuantity: 0
},
render() {
return (
<div>
<h1>Shopping Area</h1>
{Object.values(items).map(item => (
<div key={item.id}>
<h2>{item.name}</h2>
<h2>$ {item.price}</h2>
{item.remaining === 0 ? (
<p style={{ 'color': 'red' }}>Sold Out</p>
) : (
<div>
<p>Remaining: {item.remaining}</p>
<input
type="number"
value={ itemQuantity }
onChange={e => this.setState({ itemQuantity: e.target.value})}
placeholder="quantity"
min={1}
max={5}
/>
<button onClick={() => this.addItem(item)}>Add To Cart</button>
</div>
)}
</div>
))}
</div>
)
}
}
答案 0 :(得分:3)
如果对所有输入使用相同的状态键,则所有输入都从一个位置获取值并更新到一个位置。为避免这种情况,您必须使用单独的状态。我想您正在尝试显示项目列表的输入。
要实现,您可以为列表项创建组件并在列表项组件中保持状态。由于每个组件都有自己的状态,因此状态值不会发生冲突。
这是一个例子
class CardItem extends Component {
state = {
number: 0
}
render() {
render (
<input type="text" value={this.state.number} onChange={e => this.setState({ number: e.target.value })} />
)
}
}
class Main extends Component {
render () {
const list = [0,1,2,3,4]
return (
list.map(item => <CardItem data={item} />)
)
}
}
答案 1 :(得分:1)
以下是我通常如何处理这种情况。你说你得到一系列物品?每个item对象都应包含一个用于存储值的键(在我的示例中为count
)。您可以使用通用的onChange处理程序来更新数组中的单个项目。所以现在,您的州正在管理项目列表而不是每个单独的输入值。这使您的组件更加灵活,并且能够处理任何数量的项目而无需更改代码:
const itemData = [
{ id: 0, count: 0, label: 'Number 1' },
{ id: 1, count: 0, label: 'Number 2' },
{ id: 2, count: 0, label: 'Number 3' },
{ id: 3, count: 0, label: 'Number 4' }
];
class App extends React.Component {
state = {
items: itemData
}
handleCountChange = (itemId, e) => {
// Get value from input
const count = e.target.value;
this.setState( prevState => ({
items: prevState.items.map( item => {
// Find matching item by id
if(item.id === itemId) {
// Update item count based on input value
item.count = count;
}
return item;
})
}))
};
renderItems = () => {
// Map through all items and render inputs
return this.state.items.map( item => (
<label key={item.label}>
{item.label}:
<input
type="number"
value={item.count}
onChange={this.handleCountChange.bind(this, item.id)}
/>
</label>
));
};
render() {
return (
<div>
{this.renderItems()}
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
label {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
答案 2 :(得分:1)
这是一个解决方案,该问题被宽泛地解释,但它确实可以工作而无需创建另一个组件。如您所知,您需要分离购物车中每件商品的状态。我通过动态初始化和设置每个项目的数量状态来做到这一点。您可以通过此示例查看状态更改:
class App extends React.Component {
constructor(props) {
super(props);
this.state = { quantities: {} }
}
componentDidMount() {
let itemIDs = ['1', '2', '3', 'XX']; //use your own list of items
itemIDs.forEach(id => {
this.setState({quantities: Object.assign(this.state.quantities, {[id]: 0})});
})
}
render() {
let list = Object.keys(this.state.quantities).map(id => {
return (
<div>
<label for={id}>Item {id}</label>
<input
id={id}
key={id}
type="number"
value={this.state.quantities[id]}
onChange={e => {
this.setState({quantities: Object.assign(this.state.quantities, {[id]: e.target.value})})
}}
/>
</div>
);
})
return (
<div>
{list}
<div>STATE: {JSON.stringify(this.state)}</div>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>
您可以根据自己的喜好修改状态结构。
答案 3 :(得分:0)
您不能对两个输入使用相同的状态。尝试为每个人使用不同的状态:
class App extends Component {
state = {
number: ""
}
render() {
return (
<div>
<input
type="number"
value={this.state.number}
onChange={e => this.setState({ number: e.target.value })}
/>
<input
type="number"
value={this.state.number2}
onChange={e => this.setState({ number2: e.target.value })}
/>
</div>
)
}
}