如何在状态更改时重新渲染功能组件?

How to rerender functional component on state change?

我希望我的功能组件在状态“dataRes”更改时重新呈现。下面的代码是整个组件,但在第一次登录时我必须手动重新加载以显示 avatar/username 等

只要“loggedin”变为“true”,它就会重新呈现并显示用户名。好吧,显示效果非常好,只是第一次重新渲染没有...

分量:

function Username() {
  const cookies = new Cookies();

  const [username, setUsername] = useState(false);
  const [loading, setLoading] = useState(true);
  const [shortened, setShortened] = useState(false)
  const authLink = "https://discord.com/api/oauth2/authorize?client_id=" + clientID + "&redirect_uri=" + clientRedirect + "&response_type=code&scope=identify%20guilds"
  const [loggedin, setLoggedin] = useState(false);
  const history = useHistory();
  const [data, setData] = useState(null);
  const [dataRes, setDataRes] = useState(false);

  useEffect(() => {
    fetch('SomeAPIUrlHere', {
      method: "POST",
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ token: cookies.get("someCookie") })
    })
    .then((res) => res.json())
    .then((data) => {
      setData(data)
      setDataRes(true)
    })
  }, []);

  try {
    if(dataRes !== false) {
      if(data.username) {
        if(username != data.username){
          if(data.username.length > 10) {
            setShortened(true)
          }
          setDataRes(false)
          setUsername(true)
          setLoggedin(true)
          setLoading(false)
        }
      }
    }
  } catch(error) {
    console.log(error)
  }

  useEffect(() => {
    setTimeout(() => {
      setLoading(false)
    }, 1000)
  }, [])

  const SignOut = () => {
    const cookies = new Cookies();
    cookies.remove("us_au_tok")
    history.push("/")
    window.location.reload(false)
  }

  return(
    <div className="flex float-left">
      <a href={loggedin === false ? authLink : "/dashboard"} className={loggedin === false ? "shadow-2xl text-center  text-white bg-gray rounded-2xl p-2 lg:px-5 md:px-5 sm:pl-3.5 xs:pl-3.5 mr-2 block lg:w-40 md:w-40" : "text-center text-white  rounded-2xl p-2 lg:px-5 md:px-5 sm:pl-3 xs:pl-3 mr-2 block lg:w-48 md:w-48"}>
        <div className={loading === true ? "md:w-8 lg:w-8 sm:w-7 xs:w-7 m-auto text-center" : "m-auto text-center"}>
          <div className="flex justify-nter">
            {loggedin === true ? <img src={"https://cdn.discordapp.com/avatars/" + data.userid  + "/" + data.avatar + ".png?size=1024"} alt="Useravatar" className="lg:max-h-50 md:max-h-50 sm:max-h-35 xs:max-h-35 rounded-full mr-2"></img> : ""}
            {loading === true ? <img src={LoadingSVG} alt='Loading Animation'/> : <p className="hover:text-brightgray duration-300 lg:m-auto md:m-auto sm:my-auto xs:my-auto">{loggedin === true ? <span>{shortened === false ? data.username : data.username.substring(0, 10) + "..."}</span> : "Login"}</p> }
          </div>
        </div>
      </a>
      {loggedin === true ? <button onClick={SignOut}><FontAwesomeIcon icon={faSignOutAlt} className="text-white mr-4" title="Sign Out" /></button> : ""}
    </div>
  )
};

您应该将 dataRes 作为第二个参数传递给 useEffect

The second argument to useEffect is an array of dependencies . If you want to control when effect is to be executed after mounting the component, then pass an array of dependencies as the second argument

这是一个示例:

 const {useEffect,useState} = React;

function App () {
  const [data, setData] = useState(null);
  const [dataRes, setDataRes] = useState(false);
  useEffect(() => {
    if (dataRes) {
      fetch("https://gorest.co.in/public/v1/users", {
        method: "GET"
      })
        .then((res) => res.json())
        .then((data) => {
          setData(data);
          //setDataRes(true);
        });
    } else {
      setData([]);
    }
  }, [dataRes]);
  const handleClick = () => {
    setDataRes((prev) => !prev);
  };
  return (
    <div className="App">
       <button onClick={handleClick}>change dataRes</button>
      <div>{`dataRes: ${dataRes}`}</div>
      <hr />
      <div>{JSON.stringify(data)}</div>
    </div>
  );
}

ReactDOM.render( <App/> ,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>