问题描述
我有这个React组件,如下所示:
const ProductCell = (props) => {
const [option,setoption] = useState();
return(
<div>
<NativeSelect
value={option}
onChange={e => setoption(e.target.value)}
>
{props.product.variations.nodes.map( // here I extracted all the item
(item,i) => (
<option value={item} key={i}>{item.name}</option> // set option value to item object
))
}
</NativeSelect>
<Typography variant="h5" className={classes.title}>
{option.price} // I want to update the value of price according to the selected option.
</Typography> // according to the selected option above
</div>
)
}
我有一个NativeSelect
组件,它来自React Material-Ui,所以基本上是一个Select
html标记。在上面的代码中,我要做的是提取props.product.variations.nodes
内的所有元素,并将提取的item
放入所有元素,然后将每个元素放入<options/>
标记中。
item的Json对象如下所示:
"variations": {
"nodes": [
{
"id": "someId","name": "abc1234","variationId": 24,"price": "$100.00"
},{
.. another ID,name,variation and price
}
]
}
如您所见,我将id
,name
,variationId
和price
的一部分作为对象。因此,每个<option/>
标签将以item.name
的形式呈现给用户。到目前为止,这部分没有问题,可以说有5种变体,并且可以展示所有变体。
我想做的是:
我想更新<Typography />
组件下的价格值。例如,用户在Select
中选择了第3个选项,我想更新price
中第3个项目的<Typography />
值。
我尝试过的事情:
我创建了一个反应钩子const [option,setoption] = useState();
,然后当handleChange
时,我在setoption()
组件中与event.target.value
一起NativeSelect
。因此,value
标签的<option />
被设置为item
对象。
最后,我从price
部分的钩子中获得了Typography
值。
但是我得到的是:
控制台日志中的价格值为undefined
。因此我无法获得option.price
的值。
和此错误:
TypeError:无法读取未定义的属性“价格”
问题:
在上述示例中,如何在option.price
组件之外获取item.price
值(我希望它与NativeSelect
相同)?
根据目前的理解,我尽力解释。因此,任何帮助将不胜感激。
更新:
这是我在控制台记录item
部分中的variation.node.map()
对象和data
部分中的onHandleChanged
对象时得到的结果,但是也产生了相同的结果:
解决方法
您必须在ProductCell
组件上设置默认的选定选项。此外,当您访问onChange
上的值时,您的string
处理程序将收到object
而不是event.target.value
。
从docs
即使您在
function(event: object) => void event
:回调的事件源。您可以通过访问event.target.value
(字符串)来提取新值。
event.target.value
组件上将value
作为object
传递, NativeSelect
仍将是一个字符串。
您可能想做什么?不要将当前选定的项目设置为object
,而要使用id
并具有使用当前选定的id
查找该项目的功能。
检查下面的代码。
const ProductCell = (props) => {
const { variations } = props.product;
const { nodes } = variations;
// we're setting the first node's id as selected value
const [selectedId,setSelectedId] = useState(nodes[0].id);
const getSelectedPrice = () => {
// finds the node from the current `selectedId`
// and returns `price`
const obj = nodes.find((node) => node.id === selectedId);
return obj.price;
};
function onChange(event) {
// event.target.value will be the id of the current
// selected node
setSelectedId(parseInt(event.target.value));
}
return (
<div>
<NativeSelect value={selectedId} onChange={onChange}>
{nodes.map((item,i) => (
<option value={item.id} key={i}>
{item.name}
</option>
))}
</NativeSelect>
<Typography variant="h5">{getSelectedPrice()}</Typography>
</div>
);
};
还要注意,在我们的每个id
上都将value
作为option
道具传递。
<option value={item.id} key={i}>
现在我们如何显示price
,我们称之为getSelectedPrice()
。
更新
我认为一个更好的解决方案。我意识到,您可以将selected
状态设置为对象,并在onChange
处理程序上给定id
中的event.target.value
在nodes
上找到该项并进行设置作为您新的selected
状态。
const ProductCell = (props) => {
const { variations } = props.product;
const { nodes } = variations;
const [selected,setSelected] = useState(nodes[0]);
function onChange(event) {
const value = parseInt(event.target.value);
setSelected(nodes.find((node) => node.id === value));
}
return (
<div>
<NativeSelect value={selected.id} onChange={onChange}>
{nodes.map((item,i) => (
<option value={item.id} key={i}>
{item.name}
</option>
))}
</NativeSelect>
<Typography variant="h5">{selected.price}</Typography>
</div>
);
};