Hooki reactowe: dispatch action from useEffect
Moja struktura folderów:
|--App
|--Components
|--PageA.js
|--PageB.js
|--PageC.js
|--common-effects
|--useFetching.js
Refaktoryzuję mój kod do pobierania danych z API, używając reactowych hooków . Chcę wysłać akcję z useEffect w useFetching.js, który jest przechwytywany przez Saga middleware. Akcja powinna być wysłana tylko wtedy, gdy komponenty (PageA, PageB, PageC).
Używam redux, react-redux oraz redux-saga .
PageA.js :
function(props) {
useFetching(actionParams)
//....//
}
Podobny kod dla pageb i PageC komponentów.
Pobrałem kod wielokrotnego użytku, aby pobrać dane w useFetching
własny hak .
useFetching.js
const useFetching = actionArgs => {
useEffect( () => {
store.dispatch(action(actionArgs)); // does not work
})
}
Nie wiem jak uzyskać dostęp do redux dispatch
w useFetching. Próbowałem z efektem useReducer
, ale sagi ominęły akcję.
5 answers
Trzeba by przekazać do haka albo bound Action creators albo referencję do dispatch
. Pochodziły one z podłączonego komponentu, tak samo jak normalnie używałbyś Reacta-Redux:
function MyComponent(props) {
useFetching(props.fetchSomething);
return <div>Doing some fetching!</div>
}
const mapDispatch = {
fetchSomething
};
export default connect(null, mapDispatch)(MyComponent);
Hook powinien następnie wywołać związanego kreatora akcji w efekcie, który odpowiednio wyśle akcję.
Należy również pamiętać, że bieżący hook uruchomi efekt Co, gdy komponent zostanie ponownie wyrenderowany, a nie tylko za pierwszym razem. Musisz zmodyfikować hook tak:
const useFetching = someFetchActionCreator => {
useEffect( () => {
someFetchActionCreator();
}, [])
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-28 16:51:40
Wersja wykorzystująca Hooki react-redux:
Możesz nawet całkowicie wyciąć funkcję connect używając useDispatch
z react-redux:
export default function MyComponent() {
useFetching(fetchSomething);
return <div>Doing some fetching!</div>
}
With your custom hook
import { useDispatch } from 'react-redux';
const useFetching = (someFetchActionCreator) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(someFetchActionCreator());
}, [])
}
Edit: usunięty z custom hook zgodnie z sugestią @yonga-springfield
Uwaga: React gwarantuje, że tożsamość funkcji dispatch jest stabilna i nie zmieni się przy ponownym renderowaniu. Dlatego można bezpiecznie pominąć listę zależności useEffect lub useCallback.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-26 08:52:34
To tylko po to, aby wprowadzić optymalizację do odpowiedzi @ Alex Hans.
Zgodnie z dokumentacją tutaj . Hook Niestandardowy to funkcja JavaScript, której nazwa zaczyna się od "use" i może wywoływać inne Hooki.
Mając to na uwadze, nie musimy wysyłać odwołania do funkcji dispatch do Hooka useFetching jako parametru, ale raczej po prostu nie wysyłać go i używać go z poziomu Hooka useFetching z odpowiednim importem.
Oto fragment co mam na myśli.
import { useDispatch } from 'react-redux';
const useFetching = (someFetchActionCreator) => {
const dispatch = useDispatch()
useEffect(() => {
dispatch(someFetchActionCreator());
}, [])
}
Nie mogę się upewnić, że ten przykład będzie pasował bez błędów w Twoim kodzie w Twoim przypadku, ale po prostu staram się wyjaśnić ideę / koncepcję stojącą za tym postem.
Mam nadzieję, że to pomoże każdemu przyszłemu przybyszowi.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-23 11:44:37
Alex Hans słuszna decyzja z dispatch, ale aby wyeliminować pętle żądania do api można określić zależność od dispatch (użyłem Redux Toolkit)
import React, { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import axios from 'axios'
import { getItemsStart, getItemsSuccess, getItemsFailure } from '../features/itemsSlice'
const fetchItems = () => async dispatch => {
try {
dispatch(getItemsStart());
const { data } = await axios.get('url/api')
dispatch(getItemsSuccess(data))
} catch (error) {
dispatch(getItemsFailure(error))
}
}
const PageA = () => {
const dispatch = useDispatch()
const { items } = useSelector(state => state.dataSlice)
useEffect(() => {
dispatch(fetchItems())
}, [dispatch])
return (
<ul>
{items.map(item => <li>{item.name}</li>}
</ul>
)
}
export default PageA
Ważne jest podanie parametru zależności dispatch w useEffect (() = > {...}, [dispatch])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-23 10:46:03
useEffect(() => {
fetchData();
}, []);
async function fetchData() {
try {
await Auth.currentSession();
userHasAuthenticated(true);
} catch (e) {
if (e !== "No current user") {
alert(e);
}
}
dispatch(authentication({ type: "SET_AUTHING", payload: false }));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-09 17:34:27