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

时间:2020-06-21 08:47:51

标签: reactjs asynchronous use-effect

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

问题是,在加载应用程序时,我首先得到一个空项目列表,然后突然所有信息都加载到列表中,而微调框却没有显示。我首先在app.controller('homeController', function ($scope, $location) { $scope.deviceId = $location.search().deviceId; $scope.callSource = $location.search().callSource; /* I want to call the function here*/ }); 中的一个过滤器中获取了一个过滤器,并根据该信息将这些项目自己带上。

父母正在做这样的事情:

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 false加载组件,然后实际上才调用isLoading的整个动作的原因改变状态?因为我在这里假设我首先设置了setEffect,然后进行了重新渲染,然后继续使用useEffect的其余代码。我不确定该怎么做

3 个答案:

答案 0 :(得分:1)

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

从下面移除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>

答案 1 :(得分:0)

这是加载的完整示例:

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>

答案 2 :(得分:0)

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