使用上下文进行用户登录时,React 上下文重新渲染问题

问题描述 投票:0回答:1

我在网站上实现用户登录功能时遇到了 React 上下文问题。用户可以作为虚拟用户登录,我已经使用 React 上下文实现了这一点。但是,在用户登录并离开页面后,上下文不会持续存在,使我相信该组件正在重新渲染。

Gif of issue

GitHub:GitHub 存储库

此外,您可以在直播网站上体验该问题:直播网站

如果您能帮助我理解为什么在离开页面后上下文没有持续存在,我将不胜感激。谢谢您的帮助。

import { createContext, useState } from "react";

export const UserContext = createContext();

export const UserProvider = (props) => {
  const [user, setUser] = useState("grumpy19");
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {props.children}
    </UserContext.Provider>
  );
};
import { useEffect, useState } from "react";
import { getUsers } from "../../utils/utils";
import { UserContext } from "../../contexts/UserContent";
import { useContext } from "react";
import "./Users.css";
import Spinner from "react-bootstrap/Spinner";
import { Card, CardGroup } from "react-bootstrap";
import { Badge } from "react-bootstrap";
import Stack from "react-bootstrap/Stack";

export default function Users() {
  const [users, setUsers] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [err, setErr] = useState(null);
  const { setUser, user } = useContext(UserContext);

  function handleAvatarClick(username) {
    setUser(username);
  }

  useEffect(() => {
    setIsLoading(true);
    setErr(false);
    getUsers()
      .then(({ users }) => {
        setUsers(users);
        setIsLoading(false);
      })
      .catch((err) => {
        setIsLoading(false);
        setErr(err);
      });
  }, []);

  if (err)
    return (
      <div>
        <h1>Whoops</h1>
        <h2>Status: {err.status}</h2>
        <h2>{err.msg}</h2>
      </div>
    );

  return (
    <div className="user-container">
      <h2 id="user-heading">Users</h2>
      <p id="user-desc">Click on a users image to log in</p>
      <p id="current-user">
        Hello <Badge bg="dark">{user}</Badge> !
      </p>

      {isLoading ? (
        <Spinner animation="border" variant="primary" className="spinner" />
      ) : null}

      <CardGroup id="users-list">
        <ul>
          {users.map((person, index) => {
            return (
              <Card
                key={index}
                className="user-card"
                onClick={() => {
                  handleAvatarClick(person.username);
                }}
              >
                <Stack className="user-info" direction="horizontal" gap={3}>
                  <div className="p-2">{person.name}</div>
                  <div className="p-2 ms-auto">
                    {" "}
                    <Badge>{person.username}</Badge>
                  </div>
                </Stack>

                <Card.Img src={person.avatar_url} />
              </Card>
            );
          })}
        </ul>
      </CardGroup>
    </div>
  );
}

我在之前的项目中实现了类似的代码,并且运行没有任何问题。

import { createContext, useState } from "react";

export const UserContext = createContext();

export const UserProvider = (props) => {
  const [user, setUser] = useState("Paul-R");
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {props.children}
    </UserContext.Provider>
  );
};
import { useEffect, useState } from "react";
import "./Users.css";
import { getUsers } from "../../utils.js/api";
import { UserContext } from "../../contexts/UserContent";
import { useContext } from "react";

export default function Users() {
  const [users, setUsers] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [err, setErr] = useState(null);
  const { setUser } = useContext(UserContext);

  function handleAvatarClick(username) {
    setUser(username);
  }

  useEffect(() => {
    setIsLoading(true);
    setErr(false);
    getUsers()
      .then(({ users }) => {
        setUsers(users);
        setIsLoading(false);
      })
      .catch((err) => {
        setIsLoading(false);
        setErr(err);
      });
  }, []);

  if (isLoading) return <p>Loading...</p>;

  if (err)
    return (
      <div>
        <h1>Whoops</h1>
        <h2>Status: {err.status}</h2>
        <h2>{err.msg}</h2>
      </div>
    );

  return (
    <div>
      <h1>Users</h1>
      <p>Click on a users image to log in</p>
      <ul>
        {users.map((user) => {
          return (
            <li key={user.username}>
              <p>username: {user.username}</p>
              <p>kudos: {user.kudos}</p>
              <img
                src={user.avatar_url}
                alt=""
                width="100"
                onClick={() => {
                  handleAvatarClick(user.username);
                }}
              />
            </li>
          );
        })}
      </ul>
    </div>
  );
}
reactjs react-hooks react-router react-context
1个回答
0
投票

问题是react-bootstrap的

<Nav.Link>
组件不知道你正在使用react-router,因此不与它集成。当您单击链接时,它会进行页面刷新,这会重置应用程序中的所有状态。

您可以独立使用react-router的Link组件,如下所示:

import { Link } from 'react-router';
// ...
<Link to="/">Home</Link>

或者如果你想继续使用react-bootstrap的Nav.Link,可以使用

as
属性来告诉它使用不同的组件进行渲染:

<Nav.Link as={Link} to="/">Home</Nav.Link>

或者,还有一种选择,您可以编写一个 onClick 处理程序并让它从

useNavigate
:

调用该函数
export default function Navigation() {
  const navigate = useNavigate)9;
  // ...
  <Nav.Link onClick={() => navigate("/")}>Home</Nav.Link>
}
© www.soinside.com 2019 - 2024. All rights reserved.