我正在创建一个具有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的其余代码。我不确定该怎么做
答案 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用于项目的主微调器。