【问题标题】:React render() is being called before componentDidMount()在 componentDidMount() 之前调用 React render()
【发布时间】:2018-01-02 09:05:49
【问题描述】:

在我的componentDidMount() 中,我正在进行 API 调用以获取一些数据,然后此调用设置我在渲染中使用的状态对象。

componentDidMount() {
            const { actions } = this.props;

            this.increase = this.increase.bind(this);

            // api call from the saga
            actions.surveyAnswersRequest();

            // set breadcrumb
            actions.setBreadcrumb([{ title: 'Score' }]);
            actions.setTitle('Score');
            this.increase();
        }

在我的渲染函数中,我将一些道具值传递给视图文件:

render() {
        const { global, gallery, survey_answers, survey, survey_actual_answers } = this.props;

        if (global.isFetching) {
            return <Loading />;
        }
        return this.view({ gallery, survey_answers, survey, survey_actual_answers });
    }

我遇到的问题是第一次加载页面时没有设置 survey_actual_answers 道具,但是当我刷新页面时,道具返回数据正常并且脚本的其余部分将运行。这只是它第一次为该 prop 值返回一个空数组。

这就是我传递道具的方式:

Score.propTypes = {
    actions: PropTypes.object.isRequired,
    global: PropTypes.object.isRequired,
    survey: PropTypes.object.isRequired,
    survey_answers: PropTypes.object.isRequired,
    gallery: PropTypes.object.isRequired,
    survey_actual_answers: PropTypes.array.isRequired,
    survey_score_system: PropTypes.array.isRequired,
    survey_styles: PropTypes.object.isRequired,
    survey_general_doc_data: PropTypes.object.isRequired
};

function mapStateToProps(state, ownProps) {
    return {
        ...ownProps,
        global: state.global,
        gallery: state.gallery,
        survey: state.survey,
        survey_actual_answers: state.survey.survey_actual_answers,
        survey_answers: state.survey.survey_answers,
        survey_score_system: state.survey.survey_score_system,
        survey_styles: state.survey.survey_styles,
        survey_general_doc_data: state.survey.survey_general_doc_data,
        isFetching: state.isFetching
    };
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators({
            ...globalActions,
            ...galleryActions,
            ...surveyActions
        }, dispatch)
    };
}

有人知道为什么会这样吗?就好像它根本没有调用 componentDidMount。

【问题讨论】:

  • componentWillMount() 发生在 之前 render()componentDidMount() 发生在之后facebook.github.io/react/docs/…
  • 也。只需将 isFetching 设置为直接道具而不是全局对象。
  • @jered 我已经尝试将actions.surveyAnswersRequest(); 放入componentWillMount() 并仍然遇到同样的问题
  • render 总是会在您的 ajax 请求返回之前被调用。编写一些代码来处理挂起状态
  • 很难说出您的确切问题是什么。能否包含一些带有意外行为的错误或控制台日志?

标签: javascript reactjs


【解决方案1】:

这是因为 React 的基本工作原理。 React 应该让人感觉快速、流畅和活泼;应用程序永远不应该被 http 请求或异步代码阻塞。答案是使用生命周期方法来控制 DOM。

组件挂载是什么意思?

更好地理解一些 React 词汇表可能会有所帮助。当一个组件被挂载时,它被插入到 DOM 中。这是调用构造函数的时候。 componentWillMount 几乎是构造函数的同义词,并且大约在同一时间被调用。 componentDidMount 只会在第一次渲染后调用一次。

componentWillMount --> 渲染 --> componentDidMount

这与重新渲染或更新有何不同?

现在组件在 DOM 中,您想要更改显示的数据。当调用 setState 或从父组件传递新的 props 时,将发生组件更新。

componentWillRecieveProps --> shouldComponentUpdate-->componentWillUpdate
-->渲染-->componentDidUpdate

还需要注意的是,http 请求通常在 componentDidMount 和 componentDidUpdate 中完成,因为我们可以在这些地方使用 setState 触发重新渲染。

那么如何在渲染发生之前获取数据呢?

嗯,人们有几种方法可以解决这个问题。第一个是在您的组件中设置一个初始状态,以确保如果来自 http 请求的数据尚未到达,它不会破坏您的应用程序。在 http 请求完成之前,它将使用默认或空状态。

我通常不喜欢加载模式,但有时它是必要的。例如,当用户登录时,您不想将他们带到您网站的受保护区域,直到他们完成身份验证。我尝试做的是在用户登录时使用该加载模式,以便在不影响用户体验的情况下尽可能多地加载数据。

您还可以使组件显示为正在加载,而不会影响网站其余部分的用户体验。我最喜欢的例子之一是Airbnb website。请注意,该站点的大部分内容都可以使用,您可以滚动、单击链接,但“体验”下的区域处于加载状态。这是使用 React 的正确方法,也是 setState 和 HTTP 请求在 componentDidMount/componentDidUpdate 中完成的原因。

【讨论】:

  • 非常棒的答案 - 这让我看到了 React.Component 文档。在 2021 年,componentWillMount() 被认为是不安全的。但重要的部分是渲染发生在 componentDidMount 之前!
【解决方案2】:

在 componentdidmount 中使用 setState。这是我的代码:

 async componentDidMount() {

    danhSachMon = await this.getDanhSachMon();
    danhSachMon=JSON.parse(danhSachMon);
    this.setState(danhSachMon);
}

render() {
    return (
        <View>
            <FlatList
                data={danhSachMon}
                showsVerticalScrollIndicator={false}
                renderItem={({ item }) =>
                    <View >
                        <Text>{item.title}</Text>
                    </View>
                }
                keyExtractor={(item, index) => index.toString()}
            />
        </View>
    )
}

【讨论】:

    【解决方案3】:

    componentWillMount 已弃用。现在您需要使用“DidMount”,一旦它完成并更改渲染时的 DOM,react 将处理其他所有事情。

    确保在渲染中更新并使用正确的变量/状态/道具。

    componentDidMount() {    
        const { applicationId } = this.props;
        if (applicationId) {
          ApplicationService.getQuotesByApplicationId(applicationId).then((response) => {
            const quotes = _.get(response, 'data.data');
            this.setState({
              quotes,
            });
          });
    
        ....
    
        }
    
        render() {
    
            const quotes = _.get(this.state, 'quotes', null);
            return (
              <div className="application">
                <h4 className="application__sub">Application</h4>
                <h1 className="application__title">Quote Comparison</h1>
                <div className="form-wrapper">
                  {this.renderQuotes(quotes)}
                </div>
                <div />
              </div>
            );
          }
    

    在这里,我从 API 中获取引号,并在它完成后立即在状态中设置一个变量,然后渲染和反应完成它们的工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-19
      • 2020-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-16
      相关资源
      最近更新 更多