React Hooks Map不是函数

时间:2019-04-25 14:06:50

标签: javascript reactjs

我想做的很简单。我有两个按钮,一个表示打开,另一个表示关闭。当我单击其中之一时,我想使用新设置的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>
    )
}

如果有人能指出我正确的方向,那将很棒。

5 个答案:

答案 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)

您的代码有几个问题。

1。您不能在return内声明变量

您需要先声明变量,然后才能在{ }

中使用它

错误

{
    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 (
    ...
)

2。您不能只调用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

3。您需要在.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)

您正在做多项错误的事情。

  1. 应为onClick提供回调/函数,而不是函数执行输出
  2. 您正在使用对象覆盖列表/数组值

您需要更新特定索引上的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
        },

    ]);