英文:
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>
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论