使用 navigate('/path') 后重新渲染组件



在这种情况下,当用户登录时,他将被重定向到消息页面。我希望header组件在此之后呈现,但它没有发生。如果标题被呈现,链接将会改变,但如果不被呈现,链接将保持不变,直到页面刷新…我能做什么?!

login.js:

const login = async (e) => {
e.preventDefault();
const result = await (
await fetch("/portfolio/login", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
).json();
if (result.accessToken) {
navigate("/message");    //imported from @reach/router
} else console.log(result.error);
if (result.message) setRes(result.message);
};

header.js:

const Header = () => {
const [tokenObj, setToken] = useState('');

useEffect(() => {
fetch('/portfolio/verify', {method : "GET"})
.then((res)=>{
if(res.ok) return res.json(res);
})
.then((jsonRes)=> {
if(jsonRes.token) setToken(jsonRes.token)
});
}, [tokenObj]);
let lastNavLink;
let lastNavHref;
if(tokenObj){ 
lastNavLink = 'Messages';
lastNavHref = '/message'
} else {
lastNavLink = 'Login';
lastNavHref = '/login';
}
return <a href={lastNavHref}> {lastNavLink} </a> //dynamic link
};

在进入解决方案之前需要记住两件事:

  1. 组件重新渲染基于状态或道具的变化,就是这样。
  2. 你必须在浏览器中保存你的登录信息,比如localStorage,这样你就知道用户是否登录了,不管重新加载你的页面。

所以回来,你必须有条件地呈现基于登录信息的链接(它可以是任何东西,但最可能的是用户信息和/或访问/授权令牌),你将在登录后保存在浏览器本地存储。但是有一个问题,从localStorage保存和获取登录数据是不够的,因为我们需要状态或道具形式的数据,因为只有这样组件才会对更改做出反应。因此,为了解决这个问题,您必须以某种方式同步localStorage中的数据与state/prop。

要实现这一点,可以使用redux,react-reduxredux-persist的组合来解决这个问题。所以基本上它的工作方式与正常的redux流工作方式相同,但主要的变化将通过redux-persist持久化您的登录信息来完成。一旦你用redux-persist包装你的登录减速器,它会自动保存/同步你的登录减速器与localStorge。您可能会找到很多这样的例子。因此,您将在收到响应后调度登录操作,并将相关数据作为其参数(将保存在存储中),其余的将由redux处理。之后,你只需要得到你的登录状态从redux在你的头,并基于有条件地呈现你的链接。

这是一个可能的解决方案,但无论如何你知道它是如何工作的。如果你愿意,你可以用Context代替Redux,但无论如何你都明白了。