简体   繁体   English

加载微调器未显示在 React 组件中

[英]Loading spinner not showing in React Component

I am creating a React.js app which got 2 components - The main one is a container for the 2nd and is responsible for retrieving the information from a web api and then pass it to the child component which is responsible for displaying the info in a list of items.我正在创建一个包含 2 个组件的 React.js 应用程序 - 主要的一个是第二个组件的容器,负责从 web api 检索信息,然后将其传递给负责在物品清单。 The displaying component is supposed to present a loading spinner while waiting for the data items from the parent component.显示组件应该在等待来自父组件的数据项时呈现一个加载微调器。

The problem is that when the app is loaded, I first get an empty list of items and then all of a sudden all the info is loaded to the list, without the spinner ever showing.问题是,当应用程序加载时,我首先得到一个空的项目列表,然后突然所有信息都加载到列表中,而微调器从未显示。 I get a filter first in one of the useEffects and based on that info, I am bringing the items themselves.我首先在其中一个useEffects中获得了一个过滤器,然后根据该信息,我自己带来了这些项目。

The parent is doing something like this:父母正在做这样的事情:

useEffect(() =>
{
    async function getNames()
    {
        setIsLoading(true);
        const names = await WebAPI.getNames();
        setAllNames(names);
        setSelectedName(names[0]);
        setIsLoading(false);
    };
    getNames();
  } ,[]);

  useEffect(() =>
  {
    async function getItems()
    { 
        setIsLoading(true);
        const items= await WebAPI.getItems(selectedName);
        setAllItems(items);
        setIsLoading(false);
    };
    getTenants();
  },[selectedName]);

  .
  .
  .
  return (
     <DisplayItems items={allItems} isLoading={isLoading} />
   );

And the child components is doing something like this:子组件正在做这样的事情:

let spinner = props.isLoading ? <Spinner className="SpinnerStyle" /> : null; //please assume no issues in Spinner component
let items = props.items;
return (
   {spinner}
   {items}
)

I'm guessing that the problem is that the setEffect is asynchronous which is why the component is first loaded with isLoading false and then the entire action of setEffect is invoked before actually changing the state?我猜问题在于setEffect是异步的,这就是为什么首先使用isLoading false 加载组件,然后在实际更改 state 之前调用setEffect的整个操作? Since I do assume here that I first set the isLoading and then there's a rerender and then we continue to the rest of the code on useEffect.因为我在这里假设我首先设置了isLoading ,然后进行了重新渲染,然后我们继续使用 useEffect 上的代码的 rest。 I'm not sure how to do it correctly我不确定如何正确执行

The problem was with the asynchronicity when using mulitple useEffect.问题在于使用多个 useEffect 时的异步性。 What I did to solve the issue was adding another spinner for the filters values I mentioned, and then the useEffect responsible for retrieving the values set is loading for that specific spinner, while the other for retrieving the items themselves set the isLoading for the main spinner of the items.我为解决这个问题所做的是为我提到的过滤器值添加另一个微调器,然后负责检索值集的useEffect正在为该特定微调器加载,而另一个用于检索项目本身的则为主微调器设置 isLoading的项目。

instead of doing it like you are I would slightly tweak it:而不是像你那样做,我会稍微调整一下:

remove setIsLoading(true);删除setIsLoading(true); from below从下面

useEffect(() =>
{
    async function getNames()
    {
        setIsLoading(true); //REMOVE THIS LINE
        const names = await WebAPI.getNames();
        setAllNames(names);
        setSelectedName(names[0]);
        setIsLoading(false);
    };
    getNames();
  } ,[]);

and have isLoading set to true in your initial state.并在您的初始 state 中将isLoading设置为true that way, it's always going to show loading until you explicitly tell it not to.这样,它总是会显示加载,直到你明确告诉它不要。 ie when you have got your data即当你有你的数据

also change the rendering to this:还将渲染更改为:

let items = props.items;
return isLoading ? (
   <Spinner className="SpinnerStyle" />
) : <div> {items} </div>

this is full example with loading:这是加载的完整示例:

 const fakeApi = (name) => new Promise((resolve)=> { setTimeout(() => { resolve([{ name: "Mike", id: 1 }, { name: "James", id: 2 }].filter(item=>item.name===name)); }, 3000); }) const getName =()=> new Promise((resolve)=> { setTimeout(() => { resolve("Mike"); }, 3000); }) const Parent = () => { const [name, setName] = React.useState(); const [data, setData] = React.useState(); const [loading, setLoading] = React.useState(false); const fetchData =(name) =>{ if(;loading) setLoading(true). fakeApi(name);then(res=> setData(res) ) } const fetchName = ()=>{ setLoading(true). getName().then(res=> setName(res)) } React;useEffect(() => { fetchName(), }; []). React;useEffect(() => { if(name)fetchData(name), }; [name]). React,useEffect(() => { if(data && loading) setLoading(false) }; [data])? return ( <div> {loading. "Loading..:". data && data.map((d)=>(<Child key={d.id} {..;d} />))} </div> ); }, const Child = ({ name.id }) =>(<div>{name} {id}</div>) ReactDOM,render(<Parent/>.document.getElementById("root"))
 <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script> <div id="root"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM