gpt4 book ai didi

reactjs - 在 React 中,如何在所有组件中拥有一个自定义钩子(Hook)的单个实例?

转载 作者:行者123 更新时间:2023-12-04 01:08:56 25 4
gpt4 key购买 nike

我有几个组件需要访问相同的玩家列表。
这个球员名单不会改变,但我不知道哪个组件首先需要它。
我的想法是,首先需要它的组件(axios 请求)更新我的 redux 存储,然后其他组件将为此使用相同的自定义钩子(Hook)。

export default function usePlayersList() {
const {list, loading, error} = useSelector(state => state.accounts.players)
const dispatch = useDispatch()

useEffect(() => {
try {
const response = authAxios.get(endpoints.players.retrieve)
response.then(res => {
dispatch({
type: "SET_PLAYERS_LIST",
payload: {
error: false,
loading: false,
list: res.data.payload
}
})
})
} catch (e) {
console.log(e)
dispatch({
type: "SET_PLAYERS_LIST",
payload: {
error: true,
loading: false,
list: []
}
})
}
}, [dispatch])
return {list, loading, error}
}
这是我的自定义钩子(Hook)。想知道这样做是否有任何不便,甚至更好的模式。提前致谢。
顺便说一句...更好的是,我会在我的 usePlayersList 中将加载和错误设置为 useState 变量(而不是将它们发送到 redux 状态)。由于这导致我出错(加载和错误在每个组件上变得不同,假设这种状态对每个组件都是独立的)我将它们发送到存储。
最好的祝福,
费利佩。

最佳答案

TL;DR 使用 Context
解释:
每个组件都获取其自定义 Hook 的实例。
在下面的示例中,我们可以看到调用 setState更改 Bla 中的状态组件,但不在 Foo 中零件:

const { Fragment, useState, useEffect } = React;

const useCustomHook = () => {
const [state, setState] = useState('old');
return [state, setState];
};

const Foo = () => {
const [state] = useCustomHook();
return <div>state in Foo component: {state}</div>;
};

const Bla = () => {
const [state, setState] = useCustomHook();
return (
<div>
<div>state in Bla component: {state}</div>
<button onClick={() => setState("new")}>setState</button>
</div>
);
};

function App() {
return (
<Fragment>
<Foo />
<Bla />
</Fragment>
);
}

ReactDOM.render(<App />, document.querySelector('#root'));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>

Context 的组合和自定义 Hook 可用于解决上述问题:

const { createContext, useContext, useState, useEffect } = React;

const Context = createContext();
const ContextProvider = ({ children }) => {
const value = useState("old");
return <Context.Provider value={value} children={children} />;
};

const useCustomHook = () => {
const [state, setState] = useContext(Context);
return [state, setState];
};

const Foo = () => {
const [state] = useCustomHook();
return <div>state in Foo component: {state}</div>;
};

const Bla = () => {
const [state, setState] = useCustomHook();
return (
<div>
<div>state in Bla component: {state}</div>
<button onClick={() => setState("new")}>setState</button>
</div>
);
};

function App() {
return (
<ContextProvider>
<Foo />
<Bla />
</ContextProvider>
);
}


ReactDOM.render(<App />, document.querySelector('#root'));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>


特定于OP想要的原始答案:
定义上下文:
import React from 'react';

const PlayersContext = React.createContext();
const PlayersProvider = PlayersContext.Provider;

export const usePlayersContext = () => React.useContext(PlayersContext);

export default function PlayersProvider({ children }) {
// add all the logic, side effects here and pass them to value
const { list, loading, error } = useSelector(
(state) => state.accounts.players
);
const dispatch = useDispatch();

useEffect(() => {
try {
const response = authAxios.get(endpoints.players.retrieve);
response.then((res) => {
dispatch({
type: 'SET_PLAYERS_LIST',
payload: {
error: false,
loading: false,
list: res.data.payload,
},
});
});
} catch (e) {
console.log(e);
dispatch({
type: 'SET_PLAYERS_LIST',
payload: {
error: true,
loading: false,
list: [],
},
});
}
}, [dispatch]);

return <PlayersProvider value={{ list, loading, error }}>{children}</PlayersProvider>;
}
添加 PlayersProvider作为需要访问玩家的组件的父级。
在这些子组件内部:
import {usePlayersContext} from 'contextfilepath'

function Child() {

const { list, loading, error } = usePlayersContext()
return ( ... )
}
您还可以在 Provider 中维护状态本身而不是在 redux 中。

关于reactjs - 在 React 中,如何在所有组件中拥有一个自定义钩子(Hook)的单个实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65439443/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com