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

请教下 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.1k
1 个回答

组件的封装,个人经验,仅供参考
1、封装组件就要考虑它的通用行,举个例子:比如封装一个 select 组件。
c446cd32f94a110708430587796d5ea9.png
上边的封装是基于 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 (
    // ...用户列表渲染代码保持不变
  );
};
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题