将状态变量作为参数的 React 组件不在更新时呈现

React component that takes state variable as a parameter not rendering on update

我有一个 React 组件,它进行 AJAX 调用,设置一个状态变量,然后将该状态变量传递给一个组件。

主要成分:

export default function MyView({ assetId }) {
   const [asset, setAsset] = useState();
   const [beanstalk, setBeanstalk] = useState();
   const [loading, setLoading] = useState(true);

   useEffect(() => {
      loadAsset();
   }, []);

   const loadAsset = async () => {
        const _asset = await findAssetById(assetId);
        setLoading(false);
        if(_asset) {
            setAsset(_asset);
            await loadBeanstalk(_asset.id);
        }
    };

    const loadBeanstalk = async (assetId) => {
        const _beanstalk = await getBeanstalkFromDB(assetId);
        setBeanstalk(_beanstalk);
    };

   return (
      { loading ? (
         <div>Loading...</div>
      ) : (
         <h3>{asset.name}</h3>
         <ChildComponent beanstalk={beanstalk} />
      )}
   )
}

子组件:

export default function ChildComponent({ beanstalk }) {
   const [loadbalancer, setLoadbalancer] = useState([]);
   const [loading, setLoading] = useState(true);

   useEffect(() => {
      console.log("Beanstalk will print as undefined here:");
      console.log(beanstalk);
      getLoadbalancer();
   }, []);

   const getLoadbalancer = async () => {
      if(beanstalk) {
         const _loadbalancer = await getLoadbalancer(beanstalk);
         setLoading(false);
         setLoadbalancer(_loadbalancer);
      }
   }

   return (
      { loading ? (
         <div>Loading...</div>
      ) : (
         <h3>{loadbalancer.name}</h3>
      )}
   )
}

我的理解是主组件在状态改变时渲染,所以当我调用 setBeanstalk(_beanstalk) 时它应该使用 beanstalk 状态变量集重新渲染...那么为什么 ChildComponent 总是渲染当我知道它是从数据库返回时,Beanstalk 为 null?我知道跟渲染顺序有关系

所以问题似乎与操作顺序有关。您可以尝试执行以下操作之一:

将您的 setLoading(false) 调用移至 loadBeanstalk() 以便您的 ChildComponent 仅在您完全加载这些内容后呈现。

const loadAsset = async () => {
    const _asset = await findAssetById(assetId);
    if(_asset) {
        setAsset(_asset);
        await loadBeanstalk(_asset.id);
    } else {
        setLoading(false);
    }
};

const loadBeanstalk = async (assetId) => {
    const _beanstalk = await getBeanstalkFromDB(assetId);
    setBeanstalk(_beanstalk);
    setLoading(false);
};

beanstalk 附加到 ChildComponent 中的 useEffect 挂钩。

useEffect(() => {
  console.log("Beanstalk will print as undefined here:");
  console.log(beanstalk);
  getLoadbalancer();
}, [ beanstalk ]);