反应useState钩子-组件呈现两次

时间:2019-11-24 21:43:54

标签: reactjs react-hooks

我想知道为什么我的组件SearchResults被渲染两次。

MainPage组件中,我想将offers传递给子组件SearchResults

const mainPage = () => {

    const [offers, setOffers] = useState(null);

    useEffect(() => {
        onInitOffers();
    }, [])

    const onInitOffers = () => {
        axios.get('/offers')
            .then(response => {
                setOffers(response.data);
            })
            .catch(error => {
                console.log(error);
            })
    }


    const searchResults = (
        <SearchResults
            searchedOffers={offers}
        />
    );

    return (
        <Aux>
            <div className={classes.container}>
                <div className={classes.contentSection}>
                    {searchResults}
                </div>
            </div>
        </Aux>
    )
}

export default mainPage;

为什么组件SearchResults被渲染两次?如何使用钩子将offers正确传递给子组件?

在我的子组件SearchResults中,如果要避免错误映射的条件不是函数,则必须添加:

const searchResults = props => {


    useEffect(() => {
        console.log("RENDER");
        console.log(props.searchedOffers) --> null for the first time
    }, [props.searchedOffers]);

    let offers = null;
    if (props.searchedOffers !== null) { --> props.searchedOffers is not null after the second render
        offers = props.searchedOffers.map(offer => {
            return (
                <Grid key={offer.id}>
                    <SearchResult key={offer.id} offer={offer}/>
                </Grid>
            )
        });
    }

1 个答案:

答案 0 :(得分:3)

它被渲染了两次,因为在元素安装时,您将offers设置为null。如果要确保仅在SearchResults不是offers时渲染null组件,则可以执行以下操作:

return (
  <Aux>
    <div className={classes.container}>
      <div className={classes.contentSection}>
        {offers && <SearchResult searchedOffers={offers} />}
      </div>
    </div>
  </Aux>
)

如果您要确保offers是一个数组,则可以执行类似{Array.isArray(offers) && <SearchResult searchedOffers={offers} />}的操作。

通常在执行这样的异步操作时,您可能会选择在获取发生时实际使用三元运算符来显示加载指示符:

return (
  <Aux>
    <div className={classes.container}>
      <div className={classes.contentSection}>
        {offers ? <SearchResult searchedOffers={offers} /> : "Loading..."}
      </div>
    </div>
  </Aux>
)