如何在不更新先前渲染的情况下渲染 onClick 事件的不同数据?
How do I render different data of an onClick event without updating the previous render?
我正在使用 React/Context API/UseReducer 创建基于文本的角色扮演游戏,但首先我想练习使用 useState 以便从 onclick 事件中呈现对象。到目前为止,我设法从一个数组中渲染一个对象,显示的数据由我点击的按钮决定。问题是,每当我渲染一个对象并点击另一个按钮时,新对象就会被渲染,而前一个对象会更新为我当前点击的对象。
例如,我有8个选项可供选择:弱击1-4、中击1-2、强击和发射击。当我单击 Weak Strike 1 时,它会呈现在页面上。当我单击 Mid strike 1 时,它也会呈现在页面上,但是 Weak strike 1 更改为 Mid strike 1,所以现在我有两个 Mid strike 1。
我需要一种方法来在页面上同时呈现 Weak Strike 1 和 Mid strike,而无需一个或另一个更新以相互匹配。
代码:State Hooks
const [name, setName] = useState(rpActions.strike) //Used to set and update a strike action
const [count, setCount] = useState(0) //Used to add a component after one button click
代码:onClickHandler
const onClickHandler = (e) => {
setCount(count + 1)
setName({...name, name: e.target.value})
console.log(e.target.value)
}
代码:渲染逻辑
<button className="w3-button w3-purple" value={name[0].name} onClick={onClickHandler}>{name[0].name}</button>
<button className="w3-button w3-purple" value={name[1].name} onClick={onClickHandler}>{name[1].name}</button>
<button className="w3-button w3-purple" value={name[2].name} onClick={onClickHandler}>{name[2].name}</button>
<button className="w3-button w3-purple" value={name[3].name} onClick={onClickHandler}>{name[3].name}</button>
<button className="w3-button w3-purple" value={name[4].name} onClick={onClickHandler}>{name[4].name}</button>
<button className="w3-button w3-purple" value={name[5].name} onClick={onClickHandler}>{name[5].name}</button>
<button className="w3-button w3-purple" value={name[6].name} onClick={onClickHandler}>{name[6].name}</button>
<button className="w3-button w3-purple" value={name[7].name} onClick={onClickHandler}>{name[7].name}</button>
{[...Array(count)].map((_, i) => <BattleSelection key={i} stkName2={name.name} />)}
如果我没理解错的话,你的 name
变量应该是一个数组而不是一个对象。
您的 BattleSelection
组件读取对象 name
,它会在您每次单击按钮时更新。计数的数量无关紧要,您始终在读取最后一次点击的值。
此外,由于 rpActions 是常量,您不需要将其放在状态变量上:
const [strikes, setStrikes] = useState([]) //Used to set and update a strike action
// you can also use value here, but maybe your strike object has more attributes that you might need.
const onClickHandler = (newStrike) => {
setStrikes(_strikes => [..._strikes, newStrike])
console.log(newStrike)
}
{rpActions.map(d => (
<button className="w3-button w3-purple"
value={d.name} // not necessary anymore
onClick={() => onClickHandler(d)}
>
{d.name}
</button>
))}
{strikes.map((d) => <BattleSelection key={d.name} stkName2={d.name} />)}
name
仅存储最近点击的罢工。当您映射数组时,name.name
在每次迭代中具有相同的值。
相反,您想拥有罢工历史。创建一个数组并在每次点击时追加一个新项目。
const [names, setNames] = useState([]);
const onClickHandler = (e) => {
setNames([...names, { name: e.target.value }])
}
渲染:
names.map((item, i) => <BattleSelection key={i} stkName2={item.name} />)}
我正在使用 React/Context API/UseReducer 创建基于文本的角色扮演游戏,但首先我想练习使用 useState 以便从 onclick 事件中呈现对象。到目前为止,我设法从一个数组中渲染一个对象,显示的数据由我点击的按钮决定。问题是,每当我渲染一个对象并点击另一个按钮时,新对象就会被渲染,而前一个对象会更新为我当前点击的对象。
例如,我有8个选项可供选择:弱击1-4、中击1-2、强击和发射击。当我单击 Weak Strike 1 时,它会呈现在页面上。当我单击 Mid strike 1 时,它也会呈现在页面上,但是 Weak strike 1 更改为 Mid strike 1,所以现在我有两个 Mid strike 1。
我需要一种方法来在页面上同时呈现 Weak Strike 1 和 Mid strike,而无需一个或另一个更新以相互匹配。
代码:State Hooks
const [name, setName] = useState(rpActions.strike) //Used to set and update a strike action
const [count, setCount] = useState(0) //Used to add a component after one button click
代码:onClickHandler
const onClickHandler = (e) => {
setCount(count + 1)
setName({...name, name: e.target.value})
console.log(e.target.value)
}
代码:渲染逻辑
<button className="w3-button w3-purple" value={name[0].name} onClick={onClickHandler}>{name[0].name}</button>
<button className="w3-button w3-purple" value={name[1].name} onClick={onClickHandler}>{name[1].name}</button>
<button className="w3-button w3-purple" value={name[2].name} onClick={onClickHandler}>{name[2].name}</button>
<button className="w3-button w3-purple" value={name[3].name} onClick={onClickHandler}>{name[3].name}</button>
<button className="w3-button w3-purple" value={name[4].name} onClick={onClickHandler}>{name[4].name}</button>
<button className="w3-button w3-purple" value={name[5].name} onClick={onClickHandler}>{name[5].name}</button>
<button className="w3-button w3-purple" value={name[6].name} onClick={onClickHandler}>{name[6].name}</button>
<button className="w3-button w3-purple" value={name[7].name} onClick={onClickHandler}>{name[7].name}</button>
{[...Array(count)].map((_, i) => <BattleSelection key={i} stkName2={name.name} />)}
如果我没理解错的话,你的 name
变量应该是一个数组而不是一个对象。
您的 BattleSelection
组件读取对象 name
,它会在您每次单击按钮时更新。计数的数量无关紧要,您始终在读取最后一次点击的值。
此外,由于 rpActions 是常量,您不需要将其放在状态变量上:
const [strikes, setStrikes] = useState([]) //Used to set and update a strike action
// you can also use value here, but maybe your strike object has more attributes that you might need.
const onClickHandler = (newStrike) => {
setStrikes(_strikes => [..._strikes, newStrike])
console.log(newStrike)
}
{rpActions.map(d => (
<button className="w3-button w3-purple"
value={d.name} // not necessary anymore
onClick={() => onClickHandler(d)}
>
{d.name}
</button>
))}
{strikes.map((d) => <BattleSelection key={d.name} stkName2={d.name} />)}
name
仅存储最近点击的罢工。当您映射数组时,name.name
在每次迭代中具有相同的值。
相反,您想拥有罢工历史。创建一个数组并在每次点击时追加一个新项目。
const [names, setNames] = useState([]);
const onClickHandler = (e) => {
setNames([...names, { name: e.target.value }])
}
渲染:
names.map((item, i) => <BattleSelection key={i} stkName2={item.name} />)}