Я довольно новичок в хуках React в целом и очень плохо знаком с useSelector
и useDispatch
в react-redux
, но у меня возникают проблемы с выполнением простого запроса get
при загрузке моего компонента. Я хочу, чтобы get
происходил только один раз (при начальной загрузке компонента). Я думал, что знаю, как это сделать, но я столкнулся с проблемой ESLint, которая мешает мне делать то, что я понимаю как юридический код.
У меня есть этот хук, где я пытаюсь абстрагировать свой код состояния:
export const useState = () => {
const dispatch = useDispatch();
const data = useSelector((state) => state.data);
return {
data: data,
get: (props) => dispatch(actionCreators.get(props))
};
};
За вышеупомянутой функцией есть сетевой запрос, который выполняется через redux-saga
и axios
и уже некоторое время выполняется в рабочем коде. Все идет нормально. Теперь я хочу использовать его в функциональном компоненте, поэтому я написал это:
import * as React from 'react';
import { useState } from './my-state-file';
export default () => {
const myState = useState();
React.useEffect(
() => {
myState.get();
return () => {};
},
[]
);
return <div>hello, world</div>;
};
Я ожидал, что из-за того, что у моего useEffect
в качестве второго аргумента будет пустой массив, он будет выполнен только один раз, поэтому get
произойдет, когда компонент загрузится, и все.
Тем не менее, у меня ESLint работает при сохранении в Atom, и каждый раз, когда я сохраняю, он изменяет второй аргумент []
на [myState]
, результат которого:
import * as React from 'react';
import { useState } from './my-state-file';
export default () => {
const myState = useState();
React.useEffect(
() => {
myState.get();
return () => {};
},
[myState]
);
return <div>hello, world</div>;
};
Если я загружу этот компонент, то get запускает каждый рендер, что, конечно, является полной противоположностью того, что я хочу, чтобы произошло. Я открыл этот файл в текстовом редакторе, в котором не запускается ESLint при сохранении, поэтому, когда я смог сохранить useEffect
с пустым []
, он работал.
Так что я сбит с толку. Я предполагаю, что шаблон, который я использую выше, не верен, но я понятия не имею, что такое «правильный» шаблон.
Любая помощь приветствуется.
Спасибо!
UPDATE:
Основываясь на ответе Роберта Купера и связанной статье Дана Абрамова, я провел еще несколько экспериментов. Я еще не до конца, но мне удалось заставить все работать.
Большое изменение заключалось в том, что мне нужно было добавить useCallback
вокруг моих функций отправки, например:
export const useState = () => {
const dispatch = useDispatch();
const data = useSelector((state) => state.data);
const get = React.useCallback((props) => dispatch({type: 'MY_ACTION', payload:props}), [
dispatch
]);
return {
data: data,
get: get,
};
};
Должен признать, я не до конца понимаю, зачем мне нужен обратный вызов, но он работает.
В любом случае, мой компонент выглядит так:
import * as React from 'react';
import { useState } from './my-state-file';
export default () => {
const {get, data} = useState();
React.useEffect(
() => {
get();
return () => {};
},
[get]
);
return <div>{do something with data...}</div>;
};
Реальный код немного сложнее, и я надеюсь полностью выделить вызов useEffect
из компонента и поместить его либо в пользовательский хук useState
, либо в другой хук, импортированный из того же my-state-file
файл.