#javascript #reactjs #redux #react-redux #react-hooks
#javascript #reactjs #redux #реагировать-redux #реагирующие крючки
Вопрос:
У меня есть хук useEffect, который я использую в своем App.js досье. Он помещает данные в хранилище redux, которые мне нужно использовать в моем приложении. Но он рендерится до запуска useEffect, поэтому данные не определены. Затем useEffect выполняется правильно. Мне нужно, чтобы useEffect запускался до того, как что-либо будет отображено. Как я мог это сделать? Или какое другое решение я должен использовать? Я попытался полностью удалить useEffect и просто запустить действие, но это приводит к тому, что оно выполняется бесконечно. Это мой код:
function App() {
const app = useSelector(state => state.app);
const auth = useSelector(state => state.auth);
const dispatch = useDispatch();
useEffect(() => {
dispatch(authActions.checkUser());
}, [dispatch]);
console.log(auth.user); //undefined
return (
<ThemeProvider theme={!app.theme ? darkTheme : theme}>
<CssBaseline />
<React.Fragment>
{/* TODO: Display drawer only when logged in */}
{/* <Drawer></Drawer> */}
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/dashboard">
<Dashboard user={auth.user} /> //auth.user is undefined when this gets rendered
</Route>
<Route exact path="/register" component={Register} />
</Switch>
</React.Fragment>
</ThemeProvider>
);
}
export const checkUser = () => async dispatch => {
let token = localStorage.getItem("auth-token");
if (token === null) {
localStorage.setItem("auth-token", "");
token = "";
}
const tokenRes = await Axios.post("http://localhost:5000/users/tokenIsValid", null, {
headers: { "x-auth-token": token }
});
if (tokenRes.data) {
const userRes = await Axios.get("http://localhost:5000/users/", {
headers: { "x-auth-token": token }
});
dispatch({
type: CHECK_USER,
token,
user: userRes.data
});
}
};
Ответ №1:
Мне нужно, чтобы useEffect запускался до того, как что-либо будет отображено. Как я мог это сделать?
Вы не можете выполнить useEffect
run перед начальным рендерингом.
Точно так же, как componentDidMount
в компонентах класса, выполняется после первоначального рендеринга, useEffect
выполняется после первоначального рендеринга, а затем его выполнение зависит от того, передаете ли вы второй аргумент, т. Е. Массив зависимостей, в useEffect
хук.
какое другое решение я должен использовать?
Вы можете условно отображать содержимое, убедившись, что вы отображаете асинхронно извлеченные данные только после того, как они станут доступны.
return (
{ auth ? <render content> : null}
);
или
return (
{ auth amp;amp; <render content> }
);
P.S: угловые скобки < or >
не включены в синтаксис. Они просто используются в качестве заполнителя для содержимого, которое вам нужно отобразить.
Подробности см. в разделе: Реакция — условный рендеринг
Комментарии:
1. Спасибо, это работает, но, очевидно, есть небольшая задержка перед отображением содержимого рендеринга. Как я мог предотвратить эту задержку?
2. Во время загрузки данных вы можете отобразить какой-то индикатор загрузки, чтобы указать, что данные загружаются.
Ответ №2:
Альтернатива
Вы можете использовать useMemo
, который не ожидает re-render
. Он будет выполняться таким же образом на основе зависимостей, таких как useEffect.
useMemo(()=>{
doSomething() //Doesn't want until render is completed
}, [dep1, dep2])