React Custom Hooks 全局获取数据并跨组件共享? [英] React Custom Hooks fetch data globally and share across components?

查看:48
本文介绍了React Custom Hooks 全局获取数据并跨组件共享?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这个来自 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?

推荐答案

要在大型项目中跨多个组件共享状态数据,我建议使用 ReduxReact 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆