如何使用我的反应应用程序中的 useState 钩子给出的 setState 方法增加状态对象的选定索引的计数

Posted

技术标签:

【中文标题】如何使用我的反应应用程序中的 useState 钩子给出的 setState 方法增加状态对象的选定索引的计数【英文标题】:How do I increment the count of a selected index of state object using setState method given by useState hook in my react application 【发布时间】:2021-07-11 08:59:22 【问题描述】:

目标:当投票按钮发生点击事件时,将给定数组的索引更新1

我的代码:我有一个应用组件,其中有 2 个状态对象和 1 个数组

const App = () => 
    const anecdotes = [
        'If it hurts, do it more often',
        'Adding manpower to a late software project makes it later!',
        'The first 90 percent of the code accounts for the first 90 percent of the development time...The remaining 10 percent of the code accounts for the other 90 percent of the development time.',
        'Any fool can write code that a computer can understand. Good programmers write code that humans can understand.',
        'Premature optimization is the root of all evil.',
        'Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.'
    ]

    // to select anecdotes at random
    const [selected, setSelected] = useState(0);

    // elements in anecdotes
    let n = anecdotes.length;
    const [points, setPoints] = useState(() => Array(n).fill(0));

    // to use with setSelected 
    const generateRandomNumber = (min, max) => 
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min) + min); 
    

    // eventHandler
    const handleClickNext = () => 
        return setSelected(generateRandomNumber(0, n))
    

    const handleClickVote = () => 
        const copy = [...points]
        console.log(copy);
        console.log(selected);
        console.log(copy[selected]);
        console.log(points);
        return setPoints([
            copy[selected] += 1
        ])
    

    return (
        <>
            <h1>anecdoteZ</h1>
           // code...
        </>
    )


export default App;

目标:应用程序显示来自轶事数组的随机引用以及轶事投票计数和为轶事投票的能力。

问题:我认为问题在于我的handleClickVote 函数

 const handleClickVote = () => 
        const copy = [...points]
        console.log(copy);
        console.log(selected);
        console.log(copy[selected]);
        console.log(points);
        return setPoints([
            copy[selected] += 1
        ])
    

该代码适用于显示的第一个轶事,但是当我单击next quote 按钮并对其他引号进行投票时,它会在控制台中返回NaN,因为我正在记录结果。另外我认为我正在使用setPoints 错误地设置我的数组的状态。 我不想直接改变状态,我想创建一个副本并改变它来更新我的 points 数组的状态。

注意这是我的应用组件返回的内容

<>
            <h1>anecdoteZ</h1>
            <span anecdotes=anecdotes selected=selected>
                anecdotes[selected]
            </span>
            <br />
            <br />
            <span points=points selected=selected>has points[selected] votes</span>
            <br />
            <button onClick=handleClickVote>vote</button>
            <button onClick=handleClickNext>
                next anecdote
            </button>
            <br />
            <br />
            <span>Top voted anecdote</span>
        </>

【问题讨论】:

【参考方案1】:

您猜对了,问题出在handleClickVote 函数上。就目前而言,在第一次投票时,您将状态设置为一个只有一个元素的数组。

return setPoints([       // <<-- new array starts here
    copy[selected] += 1  // <<-- it's only element, will be the the result of
                         //      the increment of whatever is in copy[selected] plus 1
]);

您想要更新copy 中的任何内容,并将copy 指定为新状态。例如:

copy[selected]++;
return setPoints(copy);

或者(借用https://***.com/a/45673826),简单地说:

const handleClickVote = () => 
    return setPoints(current => Object.assign([], current, 
      [selected]: current[selected] + 1
    ));

【讨论】:

Yoshi,最后一种方法有点复杂,会从你提到的帖子中阅读更多内容。它的工作原理是,这是否符合我们不应该直接修改状态的最佳实践?当我创建一个副本然后使用 setPoints(copy) 时,这是最佳实践吗? 是的,它看起来有点吓人,尽管它实际上也创建了状态的副本。该示例使用更新程序的callback version (setPoints),它给出了当前状态。使用Object.assign([], ...),创建一个新数组,与current 合并,最后与一个新对象合并,该对象的唯一属性是您要更新的索引。【参考方案2】:

方法handleClickVote 将值设置为长度为1 的数组。 我无法对其进行测试,但我建议将其更改为:

copy[selected] += 1;
return setPoints(copy);

【讨论】:

【参考方案3】:

首先,当您将轶事长度传递给生成随机数时,它应该是anecdotes.length - 1

也无需返回setPoints - 这可能是您的问题

【讨论】:

我的generateRandomNumber函数中排除了最大值,所以我认为它会起作用 删除setPoints 的返回值,看看是否可行

以上是关于如何使用我的反应应用程序中的 useState 钩子给出的 setState 方法增加状态对象的选定索引的计数的主要内容,如果未能解决你的问题,请参考以下文章

如何在反应中使用带有useState钩子的回调[重复]

我正在学习反应,我的代码运行良好,但我如何才能一次性声明 currDate 以在全局范围内使用它以在 useState 中使用

UseState 未使用 TextInput 正确更新 |反应

反应 useState 钩子不使用 axios 调用更新

在 useState 钩子中反应设置状态

在js中使用useStates反应如何一次显示一个div