总的来说,我对 React 钩子很陌生,对useSelector
和useDispatch
in也很陌生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
and发生的网络请求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
当组件加载时会发生,就是这样。
但是,我在 Atom 中保存时运行 ESLint,每次保存时,它都会将第二个[]
参数更改为[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
用一个空白保存时[]
,它起作用了。
所以我很困惑。我的猜测是我上面使用的模式不正确,但我不知道“正确”的模式是什么。
任何帮助表示赞赏。
谢谢!
更新:
根据 Robert Cooper 的回答以及 Dan Abramov 的链接文章,我进行了更多实验。我还没有完全到位,但我设法让事情正常进行。
最大的变化是我需要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,
};
};
我必须承认,我不完全理解为什么我需要 useCallback 那里,但它的工作原理。
无论如何,然后我的组件看起来像这样:
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
文件导入的另一个钩子中。