reactjs 自定义钩子使用效果问题?

fkaflof6  于 2023-06-05  发布在  React
关注(0)|答案(1)|浏览(104)

我有2个定制的钩子。一种是处理令牌(useToken),另一种是逐个令牌解码用户(useUser)。现在我希望每次在我的自定义钩子useUser中更新token,但它从未触发,我添加了[token]作为依赖项,但没有useEffect调用。

import { useState, useEffect } from "react";

function getToken() {
  return window.localStorage.getItem("token");
}
function useToken() {
  const [token, updateToken] = useState(() => getToken());

  const setToken = (newToken) => {
    localStorage.setItem("token", newToken);
    updateToken(newToken);
  };

  return [token, setToken];
}

const getUserFromToken = (token) => {
  if (!token) return null;
  return token + Date().toString();
};
function useUser() {
  const [token] = useToken();
  const [user, setUser] = useState(() => getUserFromToken(token));

  useEffect(() => {
    if (!token) return;

    const newUser = getUserFromToken(token);
    setUser(newUser);
  }, [token]);

  return user;
}

export default function App() {
  const [token, setToken] = useToken();
  const user = useUser();
  const [userName, setUserName] = useState("");

  const handleChange = (e) => setUserName(e.target.value);

  const saveHandler = () => {
    setToken(userName);
  };

  return (
    <div className="App">
      <div>
        <input
          type="text"
          placeholder="Enter Username"
          value={userName}
          onChange={handleChange}
        />
        <button onClick={saveHandler}>Save</button>
      </div>
      <div>User - {user}</div>
    </div>
  );
}

我也尝试使用useMemo代替useUser钩子中的useEffect,但都不起作用。怎么了?

kx1ctssn

kx1ctssn1#

请允许我解释一下发生了什么。您的自定义钩子useUser正在使用它自己的 * 版本 * 的useToken钩子。因此,当通过调用setTokenApp内部更新实际令牌时,它只更新App组件内部的token
请注意,即使您更新了App中的标记,钩子useUser仍然有自己的标记版本。自定义钩子不会神奇地相互交谈,除非使用类似useContext的东西。
解决办法很简单。我们将把App的token传递给useUser钩子,一切都将正常工作。

function useUser(token) {
  const [user, setUser] = useState(() => getUserFromToken(token));

  useEffect(() => {
    if (!token) return;

    const newUser = getUserFromToken(token);
    setUser(newUser);
  }, [token]);

  return user;
}

// In App
const [token, setToken] = useToken();
const user = useUser(token);

不过,我想提出另一项忠告。我可以看到useUser钩子并没有做太多的事情。它基本上处理它得到的任何token,并在不执行任何操作的情况下溢出user。对于这个用例,保持一个单独的状态并在useUser内部使用useEffect似乎是不必要的。由于user总是从令牌中派生出来的,这似乎是使用useMemo的一个很好的例子。因此,useUser可以简化如下:

function useUser(token) {
  const user = useMemo(() => getUserFromToken(token), [token]);
  return user;
}

我希望这一切都有意义。:)

相关问题