无法弄清楚为什么 useState 钩子没有正确更新

时间:2021-05-16 17:51:27

标签: reactjs react-hooks

我只想创建一个简单的组件作为“赞”按钮。用法很简单,如果用户点击按钮,他/她的用户名将被添加到列表(一个字符串)中以验证这一点。如果再次点击按钮,他/她的用户名将从字符串中删除。

import React, { useContext, useEffect, useState } from 'react';

import classnames from 'classnames';

import HeartLike from '../../svg/HearLike/HeartLike';
import { updatePostLike } from '../../api/post';

import './PostShare.css';

const PostShare = ({likedUsers, id}) => {

    const [totalLikedUsers, setTotalLikedUsers] = useState("User 1; User 2;");
    const user = {username: "User 2"};

    useEffect(() => {
        async function updateLike(likedData) {
            const response = await updatePostLike({liked: likedData}, id);
        }

        //save to database
        updateLike(totalLikedUsers);

    }, [totalLikedUsers])

    return (
        <div className="post-share">
            <p onClick={() => {
                totalLikedUsers.includes(user.username) 
                   ? setTotalLikedUsers(likedUsers.replace(user.username + ";", "")) 
                   : setTotalLikedUsers(likedUsers + user.username + ";")
          }}><HeartLike /></p>
        </div>
    );
}

export default PostShare;

使用此代码,组件开始时将变量 totalLikedUsers 设置为:

"User 1;User 2;"

如果User 2点击de like按钮,她/他的用户名将被删除:

"User 1;"

但是如果他/她再次点击按钮并使用 setTotalLikedUsers 更新变量,结果是添加了两次,而应该只添加一次:

"User 1;User 2;User 2;"

我一直试图了解正在发生的事情,但找不到解决方案。

3 个答案:

答案 0 :(得分:1)

  1. 最好在 array 中使用 useState 而不是 string
const [totalLikedUsers, setTotalLikedUsers] = useState(['user1', 'user2']);

然后从 state 推送/删除项目。

  1. 最好将请求发送到 updateLike onClick。成功后更新状态。

答案 1 :(得分:1)

我会稍微分解一下。如果您使用组件的状态,则您的名称逻辑有效。像这样。

function App() {
    const [totalLikedUsers, setTotalLikedUsers] = useState("User 1; User 2;");
    const user = {username: "User 2"};

    return (
        <>
            <p>{totalLikedUsers}</p>
            <button onClick={() => {
                totalLikedUsers.includes(user.username)
                    ? setTotalLikedUsers(totalLikedUsers.replace(user.username + ";", ""))
                    : setTotalLikedUsers(totalLikedUsers + user.username + ";")
            }}>
                Click me
            </button>
        </>
    );
}

export default App;

在您的代码中,likeUsers 道具(来自父组件)定义了替换。确保当您单击按钮并保留更改时,父状态会得到通知。您可以将一个函数作为道具传递给孩子。例如onPress(newLikedUsers) => void

答案 2 :(得分:1)

不反对您应该使用数组而不是字符串,我只是指出您代码中的错误。

这里是您启动自定义值

const [totalLikedUsers, setTotalLikedUsers] = useState("User 1; User 2;");

但是您在这里使用了道具likedUsers

 totalLikedUsers.includes(user.username) 
                   ? setTotalLikedUsers(likedUsers.replace(user.username + ";", "")) 
                   : setTotalLikedUsers(likedUsers + user.username + ";")

状态未按预期更新,因为您混合了状态 (totalLikedUsers) 和道具 (likedUsers)。

你或许应该这样做。

 const [totalLikedUsers, setTotalLikedUsers] = useState(likedUsers); // use your props as initial data

const user = {username: "User 2"};

useEffect(() => {

   setTotalLikedUsers(likedUsers) //update the state when props change

}, [likedUsers])

const onClick = (e) => {
     //instead of using useEffect, handle your updates here.
     const newLikedData =  totalLikedUsers.includes(user.username) 
                   ? totalLikedUsers.replace(user.username + ";", "")
                   : totalLikedUsers + user.username + ";")
     const response = await updatePostLike({liked: newLikedData}, id);
     updateLike(totalLikedUsers) //assuming that likedUsers props is updated here.
}

如果您查看上面的代码,状态可能不是必需的,除非您希望在渲染时立即更改,同时等待道具更新。