我想做的很简单。我有两个按钮,一个表示打开,另一个表示关闭。当我单击其中之一时,我想使用新设置的true false值将状态设置为true或false(取决于单击的按钮)并重新呈现。但是由于某些原因,rows.map不是函数。这是我到目前为止的内容:
function Calculator() {
const [rows, setRows] = useState([
{
rowVal: 0,
editing: false,
someVal: 20
},
{
rowVal: 1,
editing: true,
someVal: 20
},
])
return(
<div className="container">
<table className="table">
<thead>
<tr>
<th className="text-center" scope="col">SomeVal</th>
</tr>
</thead>
<tbody>
{
const togOff = <button onClick={setRows({editing: false})}>Toggle Off</button>
const togOn = <button onClick={setRows({editing: true})}>Toggle On</button>
rows.map(val => {
if (val.editing === true){
togOff
} else {
togOn
}
})
}
</tbody>
</table>
</div>
)
}
如果有人能指出我正确的方向,那将很棒。
答案 0 :(得分:0)
这里发生的事情是您正在使用setRows
,就像类组件的setState
方法一样(对于更新rows
来说是很好的方法),但是它不起作用用于设置rows
以外的任何内容。如React文档中所述:
与在类组件中找到的setState方法不同,useState不会自动合并更新对象。您可以通过将函数更新程序形式与对象传播语法结合使用来复制此行为。
[...]
另一个选项是useReducer,它更适合于管理包含多个子值的状态对象。
因此,如果您想在状态中使用两个键,该怎么办?
const [state, setState] = useState({
rows: [
{
rowVal: 0,
editing: false,
someVal: 20
},
{
rowVal: 1,
editing: true,
someVal: 20
},
],
editing: false,
});
然后
setState(prevState => {...prevState, editing: true|false})
答案 1 :(得分:0)
您的代码有几个问题。
您需要先声明变量,然后才能在{ }
错误
{
const togOff = <button onClick={setRows({editing: false})}>Toggle Off</button> // wrong
const togOn = <button onClick={setRows({editing: true})}>Toggle On</button> //wrong
rows.map(val => {
if (val.editing === true){
togOff
} else {
togOn
}
})
}
右
...
const togOff = <button onClick={setRows({editing: false})}>Toggle Off</button> // outside the return
const togOn = <button onClick={setRows({editing: true})}>Toggle On</button> // outside the return
return (
...
)
setRows({editing: true})
,这将无限地重新渲染组件错误
const togOff = <button onClick={setRows({editing: false})}>Toggle Off</button> // wrong
const togOn = <button onClick={setRows({editing: true})}>Toggle On</button> //wrong
右
const togOff = <button onClick={ () => setRows({editing: false})}>Toggle Off</button> // Added arrow function
const togOn = <button onClick={ () => setRows({editing: true})}>Toggle On</button> //Added arrow function
.map
函数中返回一些内容错误
rows.map(val => {
if (val.editing === true){
togOff //wrong
} else {
togOn //wrong
}
})
右
rows.map(val => {
if (val.editing === true){
return togOff // use return
} else {
return togOn // use return
}
})
完成所有这些操作后,您仍然会遇到问题,因为setRows({editing: true})
是一个数组,而不是像rows
这样的对象,因此无法{editing: true}
请在setRows
中说明您要做什么,以便我提出答案,但是在此之前,您的错误已得到部分解决。
在错误消失后,我不能百分百确定预期的结果是什么,但是here是一个关于我认为您想要的东西的有效演示。
答案 2 :(得分:0)
您正在做多项错误的事情。
您需要更新特定索引上的editing
值,以便您的切换功能将使用index
和更新后的值。
const toggle = (index, value) => {
const newRows = [...rows];
newRows[index].editing = !value;
setRows(rows);
}
rows.map((row, index) => {
if (row.editing === true){
return <button onClick={() => toggle(index, row.editing)}>Toggle Off</button>
} else {
return <button onClick={() => toggle(index, row.editing)}>Toggle ON</button>
}
})
答案 3 :(得分:0)
由于切换没有太大不同,因此可以使用editing
标志有条件地应用setRows
参数和Off/On
文本。
这样一来,您就无法使用const
切换器了……最好还是将它们保留在JSX中,使变量声明保持在JSX之上。
也不要忘记,如果您需要将参数传递给未隐式传递的回调函数,则需要在函数中wrap
进行回调,否则将立即调用回调。
return (
<div>
{rows.map(({ editing }) => (
<button onClick={() => setRows({editing: !editing})}>Toggle {editing ? 'Off' : 'On'}</button>
)}
</div>
)
答案 4 :(得分:0)
我相信这就是您所需要的,尝试如下所示将useState更改为useReducer。
“当您具有涉及多个子值的复杂状态逻辑时,useReducer通常比useState更可取。它还可以优化触发深层更新的组件的性能,因为您可以传递下传而不是回调。”
function Calculator() {
const [rows, setRows] = useReducer(
(state, newState) => ([{ ...state, ...newState }]),
[
{
rowVal: 0,
editing: false,
someVal: 20
},
{
rowVal: 1,
editing: true,
someVal: 20
},
]);