【问题标题】:React useState hook - component is rendered twiceReact useState hook - 组件被渲染两次
【发布时间】:2019-11-24 21:43:54
【问题描述】:

我想知道为什么我的组件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 中,我必须添加 if 条件以避免错误映射不是函数:

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

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

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

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

    如果您想非常确定 offers 是一个数组,您可以执行 {Array.isArray(offers) &amp;&amp; &lt;SearchResult searchedOffers={offers} /&gt;} 之类的操作。

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

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

    【讨论】:

    • 谢谢@Nick!有用!好方法,我没有想到这样做
    猜你喜欢
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 2020-07-11
    • 1970-01-01
    相关资源
    最近更新 更多