我的 useEffect 中有一个异步请求。我注意到组件在 useEffect 完成之前被渲染。
import React, { useEffect } from 'react';
import axios from 'axios';
import './SearchWords.css';
const URL_REQUEST = 'http://myLink.com';
const SearchWords = (props) => {
const { setState } = props;
useEffect(async () => {
const data = {
sentence: props.sentence
};
await axios.post(`${URL_REQUEST}/getData`, { data })
.then((res) => {
setState(state =>({
...state,
search: res.data
}));
})
.catch((err) =>{
console.log(err);
})
}, []);
const render = () => {
if(props.search.length > 0) {
const linkMarkup = props.search.map((link) => (
<li key={link.id} className="link-list-item">
<a
href={link.link}
target="_blank"
rel="noopener noreferrer"
className="link-list-item-url"
onClick
>
{link.name}
</a>
</li>
));
return <ul className="link-list">{linkMarkup}</ul>;
} else {
return <p>No data found for: {props.sentence}</p>
}
}
return render()
}
export default SearchWords;
它正在工作,但它首先显示 No data found for: My Search String
。然后,它重新加载并显示带有结果的 <ul>
。如何避免它首先显示“未找到数据”消息。
谢谢
答案 0 :(得分:4)
最简单的调整是根据响应是否返回有条件地呈现 JSX 的该部分:
const [hasLoaded, setHasLoaded] = useState();
// ...
.then((res) => {
setState(state =>({
...state,
search: res.data
}));
setHasLoaded(true);
})
然后改变
return <p>No data found for: {props.sentence}</p>
到
return hasLoaded ? <p>No data found for: {props.sentence}</p> : <p>Loading...</p>;
答案 1 :(得分:2)
它按预期工作,阅读有关 react lifecycle 的更多信息。要在使用功能组件时处理这种情况,请使用 useState()
挂钩获取 API 状态。
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
// api call
// now after api call set setIsLoading(false);
},[]}
if(isLoading) {
// return show loading spinner
}
// else remaining code
答案 2 :(得分:1)
这就是 useEffect
的工作原理:它会安排一个副作用,在组件呈现后运行。
来自the docs:
<块引用>useEffect 有什么作用?通过使用这个 Hook,你告诉 React 你的组件需要在渲染后做一些事情。 React 会记住您传递的函数(我们将其称为“效果”),并在执行 DOM 更新后稍后调用它。在这个效果中,我们设置了文档标题,但我们也可以执行数据获取或调用其他一些命令式 API。
您可以做的是跟踪效果状态以显示加载指示器,直到它完成。
import React, { useEffect } from 'react';
import axios from 'axios';
import './SearchWords.css';
const URL_REQUEST = 'http://myLink.com';
const SearchWords = (props) => {
const { setState } = props;
const [isLoading, setLoading] = React.useState(true);
useEffect(async () => {
const data = {
sentence: props.sentence
};
await axios.post(`${URL_REQUEST}/getData`, { data })
.then((res) => {
setState(state =>({
...state,
search: res.data
}));
setLoading(false);
})
.catch((err) =>{
console.log(err);
})
}, []);
const render = () => {
if(isLoading) return "Loading...";
if(props.search.length > 0) {
const linkMarkup = props.search.map((link) => (
<li key={link.id} className="link-list-item">
<a
href={link.link}
target="_blank"
rel="noopener noreferrer"
className="link-list-item-url"
onClick
>
{link.name}
</a>
</li>
));
return <ul className="link-list">{linkMarkup}</ul>;
} else {
return <p>No data found for: {props.sentence}</p>
}
}
return render()
}
export default SearchWords;
答案 3 :(得分:-4)