英文:
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 < 50; i++)
    lst.push(i);
  return <><Child1 lst={lst} refs={refs} /> <Child2 refs={refs} /> </>;
}
Child1 Component:
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)}>{`This is item number ${item}`}</div>)}</>;
}
Child2 Component:
function Child2({ refs }) {
  useEffect(() => {
    // wait for refs[0] to be defined
    complexFunction(ref[0]) //this is undefined
  });
  return <></>;
}
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
以下是翻译好的内容:
<Child2/> 中的逻辑应该移到父组件中,因为父组件负责协调子组件。
在父组件中添加类似以下代码应该会有帮助:
  // 你应该使用一个加载标志来跟踪异步函数
  // 这在调试时非常有帮助,并且可以保持干净的界面
  // 在 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} .../>
  ...
  </>
  );
并且对 <Child1/> 进行以下更改:
const Child1 = props => {
  const ref = useRef();
  useEffect(() => {
    props.addRefToList(ref);
  });
  return <div ref={ref}>{`这是第 ${props.item} 项`}</div>;
}
英文:
The logic in <Child2/> 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 => {
    complexFunction(ref);
    const newRefList = [...refList, ref]
    setRefList(newRefList);
    if (newRefList.length === lst.length) {
      complexFunction(newRefList[0]);
    }
  }
  return <>
   {loading && <LoadingIcon/> }
  ...
  <Child1 addRefToList={addRefToList} .../>
  ...
  </>
And make this change to <Child1/>
const Child1 = props => {
  const ref = useRef();
  useEffect(() => {
    props.addRefToList(ref);
  });
  return <div ref={ref}>{`This is item number ${props.item}`}</div>
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论