繁体   English   中英

如何在反应功能组件或钩子中有效地初始化客户端注册回调

[英]How to effectively initialise client register callback in react functional component or hook

我正在尝试在反应功能组件中使用工厂类。 我需要基于组件道具进行初始化,并在第一次渲染或道具更改时进行。

这就是为什么我创建实例并将它的引用存储在 useEffect 中,该数组依赖于道具,以便在道具更改时始终获取新实例。

但是当我这样做时,需要一些特殊状态来强制组件更新。

我仍然认为有更好和更清洁的方法来做到这一点。 奇怪的是强制组件更新的虚拟状态。

所以我看起来正在运行的代码如下所示:

export const useClientLoader = (props: IClientLoaderProps) => {
    const { backend, workspace, filter } = props;
    const [,setInvalidate] = useState(0);
    const [initStatus,setInitStatus] = useState<status>("pending");

    const loaderRef = useRef<IClientLoader>();

    const invalidate = ()=>{
        // force component update via changing state
        setInvalidate(i=>i+1);
    }

    useEffect(() => {
        // init client instance
        loaderRef.current = newClientHandler(backend, workspace, filter);
        // update ref not update state and re-render component
        // so i do force to update by dummy state update
        invalidate();
    }, [backend, workspace, filter]); // I need new instance when props changed

    const onInitSuccess = () => {
        setInitStatus("success");
    };

    // I need current pointer to client instance 
    const loader = loaderRef.current;

    useEffect(() => {
        if (loader) {
            // subscribe callback
            const onInitSuccessUnsubscribe = loader.onInitSuccess(onInitSuccess);

            // init client and do magic on backend and wait for result via callback
            loader.init();
            
            return () => {
                // Unsubscribe callback 
                onInitSuccessUnsubscribe();
            };
        }
    }, [loader]); // I will do change just when I have new client instance
    
    return {
        initStatus:initStatus,
        getUser: loader?.getUser
    };
};
 

我想你可以只用一个 useEffect 来实现它,不需要分成两个然后被迫使用解决方法来触发重新渲染。 像这样:

  const loaderRef = useRef<IClientLoader>();

  const onInitSuccess = useCallback(() => {
    setInitStatus("success");
  }, []);

  useEffect(() => {
    loaderRef.current = newClientHandler(backend, workspace, filter);
    const onInitSuccessUnsubscribe = loaderRef.current.onInitSuccess(onInitSuccess);
    loaderRef.current.init();

    return () => {
      // Unsubscribe callback
      onInitSuccessUnsubscribe();
    };
  }, [backend, workspace, filter, onInitSuccess]); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM