加载微调器未显示在 React Component 中

Loading spinner not showing in React Component

我正在创建一个包含 2 个组件的 React.js 应用程序 - 主要组件是第二个组件的容器,负责从 Web api 检索信息,然后将其传递给负责在项目列表中显示信息的子组件。显示组件应该在等待来自父组件的数据项时呈现加载微调器。

问题是,当加载应用程序时,我首先得到一个空的项目列表,然后突然所有信息都加载到列表中,而微调器从未显示过。我首先在其中一个 useEffects 中获得了一个过滤器,然后根据该信息,我将自己携带物品。

家长正在做这样的事情:

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} />
   );

子组件正在做这样的事情:

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

我猜问题是 setEffect 是异步的,这就是为什么组件首先加载 isLoading false 然后调用 setEffect 的整个动作在实际改变状态之前?因为我在这里假设我首先设置了 isLoading 然后有一个重新渲染,然后我们继续 useEffect 上的其余代码。我不确定如何正确操作

我会稍微调整一下,而不是像你那样做:

从下方删除 setIsLoading(true);

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

并在初始状态下将 isLoading 设置为 true。这样,它就会一直显示正在加载,直到您明确告诉它不要显示为止。即当您获得数据时

也将渲染更改为:

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

这是加载的完整示例:

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>

问题出在使用多个 useEffect 时的异步性。我为解决这个问题所做的是为我提到的过滤器值添加另一个微调器,然后负责检索值集的 useEffect 正在为该特定微调器加载,而另一个用于检索项目本身设置 isLoading对于项目的主微调器。