React Custom Hooks 全局获取数据并跨组件共享? [英] React Custom Hooks fetch data globally and share across components?
问题描述
在这个来自 https://reactjs.org/docs/hooks-custom.html 的反应示例中,在 2 个不同的组件中使用自定义钩子来获取用户的在线状态...
in this react example from https://reactjs.org/docs/hooks-custom.html, a custom hook is used in 2 different components to fetch online status of a user...
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
然后它在下面的2个函数中使用:
then its used in the 2 functions below:
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
我的问题是,该函数是否会在导入组件的任何地方单独执行?或者是否有诸如在组件之间共享状态之类的东西,如果它被定义为单独的导出函数?例如,我只执行一次该函数,并且所有组件中的isOnline"状态都相同?
my question is, will the function be executed individually everywhere where it is imported into a component? Or is there some thing like sharing the state between components, if it is defined as a separate exported function? e.g I execute the function only once, and the "isOnline" state is the same in all components?
如果它是单独获取的,我将如何只在全局获取一次数据,然后将其传递给我的 React 应用程序中的不同组件?
And if its individually fetched, how would I have to do it to fetch data only once globally, and then pass it to different components in my React app?
推荐答案
要在大型项目中跨多个组件共享状态数据,我建议使用 Redux 或 React Context.
To share state data across multiple components in a large project, I recommend to use Redux or React Context.
尽管如此,您可以使用观察者模式(https://en.wikipedia.org/wiki/Observer_pattern):
Nevertheless, you can implement a global isOnline state using the Observer pattern (https://en.wikipedia.org/wiki/Observer_pattern):
// file: isOnline.tsx
import { useEffect, useState } from 'react';
// use global variables
let isOnline = false;
let observers: React.Dispatch<React.SetStateAction<boolean>>[] = [];
// changes global isOnline state and updates all observers
export const setIsOnline = (online: boolean) => {
isOnline = online;
observers.forEach(update => update(isOnline));
};
// React Hook
export const useIsOnline = (): [boolean, Function] => {
const [isOnlineState, setIsOnlineState] = useState<Object>(isOnline);
useEffect(() => {
// add setIsOnlineState to observers list
observers.push(setIsOnlineState);
// update isOnlineState with latest global isOnline state
setIsOnlineState(isOnline);
// remove this setIsOnlineState from observers, when component unmounts
return () => {
observers = observers.filter(update => update !== setIsOnlineState);
};
}, []);
// return global isOnline state and setter function
return [isOnlineState, setIsOnline];
}
import { useIsOnline } from './isOnline';
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useIsOnline();
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
function FriendStatus(props) {
const isOnline = useIsOnline()[0];
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
const isOnline = useIsOnline()[0];
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
Edit:在 useIsOnline
内部返回 isOnlineState
创建的 useState
而不是 isOnline
> 变量,否则 React 无法将更改传递给组件.
Edit: Inside useIsOnline
return isOnlineState
created with useState
instead of the isOnline
variable because otherwise React can't pass the changes down to the component.
Edit 2:使 useEffect
独立于 isOnlineState
,这样钩子就不会在每次变量更改时取消订阅和重新订阅.
Edit 2: Make useEffect
independent of isOnlineState
so the hook does not unsubscribe and resubscribe on each variable change.
这篇关于React Custom Hooks 全局获取数据并跨组件共享?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!