我目前正在尝试通过整个应用程序与context provider
传递数据,但是触发的挂钩仅返回其初始值,并且不重新触发。
这是我的App
主组件中的应用程序布局,该组件没有任何状态。
class App extends Component {
render() {
return (
<div>
<BrowserRouter>
<UserContextProvider>
<div className="container">
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/login" component={LoginPage} />
<PrivateRoute exact path="/secret-page" component={SecretPage} />
</Switch>
</div>
</UserContextProvider>
</BrowserRouter>
</div>
);
}
}
export default App;
无论何时App
组件首次渲染时,它都会触发UserContextProvider
,后者触发onEffect
钩子。该挂钩尝试获取数据,但是由于用户尚未登录,因此它仅返回其原始值[]
。
这里是上下文提供者
const UserContextProvider = ({children}) => {
const [userSettings, setUserSettings] = useState([]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(() => {
if (userid !== null) {
fetch(
process.env.REACT_APP_API_URL + "/authenticated/get-permissions",
requestOptions
)
.then(response => response.json())
.then(response => {
setUserSettings(response.data);
setIsLoggedIn(true);
})
.catch(error => console.log(error));
} else {
console.log(userSettings);
setIsLoggedIn(false);
}
}, []);
return (
<UserContext.Provider value={userSettings}>{children}</UserContext.Provider>
);
};
现在,当上面的代码最初触发时,userid
的值为null
,但是在LoginPage
子组件中进行身份验证之后,它将变为令牌。我的问题是,即使userid
的值在登录后发生更改,该钩子也不会再次触发。
我只想提到我从一个单独的文件中的本地存储中获取userid
值并将其导入。
我尝试在函数内部的空数组参数中设置userid
值,但这不起作用。
在useEffect
值更改后,如何使我的userid
钩再次触发?
---编辑-----
userid
是通过以下方式从名为fetchRequestOptions
的另一个文件中导入的:
import {requestOptions, userid} from "./fetchRequestOptions";
在我的fetchRequestOptions
文件中,我有以下代码:
let userid = localStorage.getItem("userid");
let accessToken = localStorage.getItem("accesstoken");
let requestOptions ={ <my request options are here>}
答案 0 :(得分:1)
为了使使用userid
的挂钩在更改时可以重新运行,您需要将其保持在一个状态内。然后,LoginPage
需要连接到上下文并使用setUserid
来更新其值。
const UserContextProvider = ({ children }) => {
const [userSettings, setUserSettings] = useState([]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
// If you are reading directly from localstorage you might
// want to use localStorage.getItem("userid") as the initial value
const [userid, setUserid] = useState(null);
useEffect(() => {
// ...
}, [userid]);
return (
<UserContext.Provider value={{ userSettings, setUserid }}>
{children}
</UserContext.Provider>
);
};
关键是userid
必须处于状态内,这样它就可以在需要其最新值的任何Component中触发新的渲染。
您可能会发现Context内有一个特定的自定义钩子可以处理用户ID的逻辑(获取和更新),这更清洁。这是一个不错的选择,但只能使userid
在此上下文中可用。如果您需要在其他地方使用它,则需要从上下文value
属性中导出它。
const useUserid = () => {
const [userid, setUserid] = useState(null);
useEffect(() => {
const fetched_userid = //...
setUserid(fetched_userid);
}, []);
return userid;
};
const UserContextProvider = ({ children }) => {
// ...
const userid = useUserid();
useEffect(() => {
// ...
}, [userid]);
return (
<UserContext.Provider value={userSettings}>{children}</UserContext.Provider>
);
};
答案 1 :(得分:0)
在useEffect挂钩中传递空数组[]意味着(根据React文档)
如果要运行效果并仅将其清理一次(在挂载和卸载时),则可以将空数组([])作为第二个参数传递。这告诉React,您的效果不依赖于道具或状态的任何值,因此它不需要重新运行
因此,我们需要传递可触发效果以重新渲染的道具/状态。
答案 2 :(得分:0)
在useEffect的依赖项数组中传递userid
作为参数。这样可以确保只要userid
发生更改,效果就可以运行。
useEffect(() => {
...
}, [userid]);