问题状态: 我想使用 fetch API 将滚动事件添加到我的组件中。然而,它可以通过 Recoil 或 Context 订阅来实现,但会触发不必要的重新渲染。 (在我的情况下,我总是在使用它们后删除获取数据,因此重新渲染会导致丢失数据错误。)无论如何,是否有副作用(类似回调,不触发重新渲染)计数应用获取并在所有情况下表现出来他们已经满了。
function Foo(){
const [data,setData] = useState(null);
useEffect(()=>{
fetch("somewhere")
.then((response)=>{
if(!response.ok){throw new Error("https error.");}
return response.json();
})
.then((json)=>{
setData(json);
})
.catch((error)=>{
console.warn(error.message);
});
},[]);
if(data === null){return(<div>LOADING...</div>);}
return(
<div id={"target-comp"}>
{data}
</div>
);
}
function initSomthingAboutDom(){
//this function should be called only when every render is completed!
const targetComp = document.getElementById("target-comp");
//something about DOM control....
}
我取得了一些成就!
FetchProvider
添加到包含 fetch 的组件的末尾。安装后,FetchProvider
可以使用 Recoil 和 useEffect
相互通信。initScroller
已满,我也无法立即调用 FetchListener
,因为它们仍在渲染中。我无法访问 DOM。所以,我用了setTimeout
。setTimeout
,我还在根元素内部添加了另一个 fetchProvider
。这可以确保 FetchListener
在渲染的最后一步表现。这样,我可以缩短时间间隔,让这个逻辑更安全。FetchProvider 和 FetchListener 的定义
const fetchAtom = new atom({key: "fetch", default: [false,false,false]});
export function FetchProvider({index}){
const [fetch,updateFetch] = useRecoilState(fetchAtom);
useEffect(()=>{
const newFetch = [fetch[0],fetch[1],fetch[3]]; newFetch[index] = true;
updateFetch(newFetch);
},[]);
return(<></>);
}
export function FetchListener(){
const fetch = useRecoilValue(fetchAtom);
useEffect(()=>{
console.log(fetch);
if(fetch.some((e)=>{return e === true;})){
setTimeout(()=>{
initScroller();
},100);
}
},[fetch]);
}
它们的用途
//SomeReactComp()
fetch bla.. bla
if(dataFromFetching === null){return(<div>LOADING</div>)}
return(
<>
<div className={"skill"}>
{topImgs}<div>{bottomImgs}</div>
</div>
<FetchProvider index={1}/>
</>
);
//RootComp
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<RecoilRoot>
<FetchListener/>
<App/>
<FetchProvider index={2}/>
</RecoilRoot>
</React.StrictMode>
);