等待React中兄弟组件构建数组。

huangapple go评论72阅读模式
英文:

Wait for an array to be built by sibling in React

问题

我有一个名为Parent的组件:

function Parent() {
  let lst = [];
  let refs = [];
  for (var i = 0; i < 50; i++)
    lst.push(i);
  return <><Child1 lst={lst} refs={refs} /> <Child2 refs={refs} /></>;
}

Child1 组件:

async function createRef(refs) {
  await sleep(3000);
  let ref = React.createRef();
  refs.push(ref);
  return ref;
}

function Child1({ lst, refs }) {
  return <>{lst.map(item => <div ref={createRef(refs)}>{`这是第 ${item} 项`}</div>)}</>;
}

Child2 组件:

function Child2({ refs }) {
  useEffect(() => {
    // 等待 refs[0] 被定义
    complexFunction(refs[0]); // 这是未定义的
  });
  return <></>;
}

Child2中,我收到了由Child1控制的refs数组,在Child1中,refs是异步构建的。我想要在调用refs[0]上的complexFunction之前等待引用完全构建。

目前我唯一的解决方案是将complexFunction传递给Child1并从那里调用它,但我不喜欢这个解决方案,因为在我的实际应用中,这需要很多基础结构更改。

我也可以在调用complexFunction之前等待几百毫秒,但这也不是首选的解决方案。

我尝试将refs更改为state变量,在Child1中设置它,并在调用complexFunction之前在Child2中检查它是否被定义,但触发了setState/渲染的无限循环。

英文:

I have a Parent component:

function Parent() {
  let lst = [];
  let refs = [];
  for (var i = 0; i &lt; 50; i++)
    lst.push(i);
  return &lt;&gt;&lt;Child1 lst={lst} refs={refs} /&gt; &lt;Child2 refs={refs} /&gt; &lt;/&gt;;
}

Child1 Component:

async function createRef(refs) {
  await sleep(3000);
  let ref = React.createRef();
  refs.push(ref);
  return ref;
}

function Child1({ lst, refs }) {
  return &lt;&gt;{lst.map(item =&gt; &lt;div ref={createRef(refs)}&gt;{`This is item number ${item}`}&lt;/div&gt;)}&lt;/&gt;;
}

Child2 Component:

function Child2({ refs }) {
  useEffect(() =&gt; {
    // wait for refs[0] to be defined
    complexFunction(ref[0]) //this is undefined
  });
  return &lt;&gt;&lt;/&gt;;
}

In Child2 I'm receiving refs array that is controlled by Child1, in Child1, refs is built asynchronously. I want to wait for the refs to be built completely before calling complexFunction on refs[0].<br>
The only solution I got now is to pass complexFunction to Child1 and call it from there, but I don't prefer this solution because in my real app it takes a lot of infrastructural changes.<br>
I also can wait for a few hundreds ms before calling complexFunction but it's also not a preferred solution.<br>
I tried to changed refs to a state variable, set it in Child1 and check if it's defined in Child2 before calling complexFunction, but it triggered infinite loop of setState/renders.

答案1

得分: 1

以下是翻译好的内容:

&lt;Child2/&gt; 中的逻辑应该移到父组件中,因为父组件负责协调子组件。

在父组件中添加类似以下代码应该会有帮助:

  // 你应该使用一个加载标志来跟踪异步函数
  // 这在调试时非常有帮助,并且可以保持干净的界面
  // 在 complexFunction 运行时,界面可能看起来很奇怪或者出现问题
  const [loading, setLoading] = useState(false);
  const [refList, setRefList] = useState([]);
  const addRefToList = ref => {
    complexFunction(ref);
    const newRefList = [...refList, ref];
    setRefList(newRefList);
    if (newRefList.length === lst.length) {
      complexFunction(newRefList[0]);
    }
  }

  return (
   {loading && <LoadingIcon/> }
  ...
  <Child1 addRefToList={addRefToList} .../>
  ...
  </>
  );

并且对 &lt;Child1/&gt; 进行以下更改:

const Child1 = props => {
  const ref = useRef();
  useEffect(() => {
    props.addRefToList(ref);
  });
  return <div ref={ref}>{`这是第 ${props.item} 项`}</div>;
}
英文:

The logic in &lt;Child2/&gt; should be moved into the parent since the parent is responsible for orchestrating the children.

Adding something like this to the parent should be helpful.

  //you should track async functions with a loading flag
  //it really helps with debugging and have a clean UI
  //The UI is likely odd looking or broken while
  //complexFunction runs.
  const [loading,setLoading] = useState(false);
  const [refList,setRefList] = useState([]);
  const addRefToList = ref =&gt; {
    complexFunction(ref);
    const newRefList = [...refList, ref]
    setRefList(newRefList);
    if (newRefList.length === lst.length) {
      complexFunction(newRefList[0]);
    }
  }

  return &lt;&gt;
   {loading &amp;&amp; &lt;LoadingIcon/&gt; }
  ...
  &lt;Child1 addRefToList={addRefToList} .../&gt;
  ...
  &lt;/&gt;

And make this change to <Child1/>

const Child1 = props =&gt; {
  const ref = useRef();
  useEffect(() =&gt; {
    props.addRefToList(ref);
  });
  return &lt;div ref={ref}&gt;{`This is item number ${props.item}`}&lt;/div&gt;
}

huangapple
  • 本文由 发表于 2023年6月11日 22:28:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76450953.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定