请问在 react 中如何实时更新状态?

作者站长头像
站长
· 阅读数 24

请教下 useState 更新的问题,有一个页面,当数据库中没有数据的时候,显示 No user,当数据库中有数据的时候,显示出真实的数据,代码如下

const [users, setUsers] = useState([]);

useEffect(() => {
  const fetchData = async () => {
    try {

      const response = await fetch(`${apiUrl}/users`, {
        method: 'GET',
        headers: {
          Authorization: `Bearer ${token}`,
        }
      });

      if (response.ok) {
        const data = await response.json();

        if (data.success) {
          setUsers(data.users);
        }

      } else {
        console.log('Other HTTP Error:', response.status);
      }

    } catch (error) {
      console.error('Error fetching users:', error);
    }
  };

  fetchData();
}, [token]);


const userList = () => {
  const activedUsers = users
  .filter((user) => user.status === 1);

  if (activedUsers.length === 0) {
    return(
      <>
      {activedUsers.length === 0 &&
        <div>No user</div>
      }
      </>
    )
  }

  return (
    <>
      {activedUsers.map((user) => (
        <div key={user.userID}>
          <Link to={`/user/${user.userID}`}>{user.Name}</Link>
        </div>
      ))}
    </>
  )
}

现在我遇到的问题是

  1. 每次访问这个页面 /users,都会显示 No user,然后过一会数据完全载入了才会显示正确的数据。查看了下,这里会渲染两次,第一次渲染 activedUsers.length 是 0,第二次渲染才会正确的载入数据。
  2. 点击任意一个用户名字后,会跳到用户的详情页面,再次访问 /users,会显示刚刚访问的这个用户的用户名,然后过一会才会自动刷新出正确的数据。

请问这个问题怎么解决,希望每次进入都是显示正确的数据。

回复
1个回答
avatar
test
2024-06-23

组件的封装,个人经验,仅供参考1、封装组件就要考虑它的通用行,举个例子:比如封装一个 select 组件。answer image上边的封装是基于 antd 4.x 版本中的组件 封装的。2、如果遇到业务需求需要根据业务场景进行再次封装 select,可使用这个封装后的进行三次业务需求的 select 组件封装。第二个问题1、第一个 useEffect 可以删掉。2、initialContent 是作为 prop 传递给组件的,它在组件挂载时会被设置为初始值。然而,由于 setTextContent 是异步的(React 的状态更新是异步的),在组件首次渲染时,textContent 的值可能还没有被更新,这可能导致组件显示上一次的内容。3、可以在组件挂载时立即设置 textContent 的值,而不是依赖于 useEffect 钩子。可以通过在组件的初始化阶段直接设置 textContent 。

type UserdetailProps = {
  onChange?: (event: React.ChangeEvent<HTMLTextAreaElement>) => void
  value?: string
}

const Userdetail = (props: UserdetailProps) => {
  const { onChange,defaultValue } = props
  const [textContent, setTextContent] = useState(defaultValue);

  const onChangeValue = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    const val = event.target.value;
   setTextContent(val)
   if(typeof onChange === 'function'){
    onChange(val)
   }
  }

  // 在组件挂载时立即设置 defaultValue 的值
  useEffect(() => {
    setTextContent(defaultValue || '');
  }, []); // 空的依赖数组确保这个 effect 只运行一次

  return (
    <div className="Userdetail">
      <textarea
        value={textContent}
        onChange={onChangeValue}
      />
    </div>
  );
};

export default Userdetail;

4、添加了一个 onChange 事件处理器来更新 textContent 的值,这样当用户在文本区域输入时,内容会实时更新。5、添加了一个外部的 onChange,可以是组件更加通用,同时在外部也能拿到实时更新的值。6、textContent 将立即被设置为 defaultValue 的值,从而避免了显示上一次内容的问题。同时,用户输入时内容也会正确更新。

第一个问题。异步导致你不能第一时间拿到最新的 userinfo,最简单的方法加个 loading

const userList = () => {
  if (isLoading) {
    // 如果数据还在加载,显示加载指示器
    return <div>Loading...</div>;
  }

  const activedUsers = users.filter((user) => user.status === 1);

  if (activedUsers.length === 0) {
    return <div>No user</div>;
  }

  return (
    // ...用户列表渲染代码保持不变
  );
};
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容