React + redux:连接组件加载时调用调度

Posted

技术标签:

【中文标题】React + redux:连接组件加载时调用调度【英文标题】:React + redux: call dispatch when connected component loads 【发布时间】:2017-09-26 16:44:25 【问题描述】:

我是新来的反应。我有一个 react + react router + redux 应用程序,我想从子组件进行调度调用。现在,调度发生在应用程序顶部的 index.js 文件中,它通过 redux thunk 操作和 api 调用从数据库加载所有数据:

const store = configureStore();
store.dispatch(loadCourses()); <-- redux thunk function calling api
store.dispatch(loadAuthors());

ReactDOM.render(
    <Provider store=store>
       <Router history=browserHistory routes=routes />
    </Provider>,
    document.getElementById('app')
);

如果我想在下面的(连接的)子组件加载时加载数据或能够刷新数据怎么办?

import React, PropTypes from 'react';
import connect from 'react-redux';
import bindActionCreators from 'redux';
import * as courseActions from '../../actions/courseActions';
import CourseList from './CourseList';
import browserHistory from 'react-router';


class CoursesPage extends React.Component 
    constructor(props, context) 
        super(props, context);
        this.redirectToAddCoursePage = this.redirectToAddCoursePage.bind(this);
    

    redirectToAddCoursePage() 
        browserHistory.push('/ReactJS/course');
    

    render() 
        const courses = this.props;
        return (
            <div>
                <div className="page-header">
                    <h3>Courses</h3>
                </div>
                <input type="submit" value="New Course" className="btn btn-default btn-toolbar pull-right" onClick=this.redirectToAddCoursePage />
                <div className="panel panel-default ">
                    <div className="panel-heading">
                        <span>&nbsp;</span>
                    </div>
                    <CourseList courses=courses />
                </div>
            </div>        
        );
    


CoursesPage.propTypes = 
    courses: PropTypes.array.isRequired,
    actions: PropTypes.object.isRequired
;

function mapStateToProps(state, ownProps) 
    return 
        courses: state.courses
    ;


function mapDispatchToProps(dispatch) 
    return 
        actions: bindActionCreators(courseActions, dispatch),
    ;


export default connect(mapStateToProps, mapDispatchToProps)(CoursesPage);

在我看来,当前的设置方式(来自我遵循的教程)在应用程序启动时从整个数据库加载所有数据效率低下,特别是如果多个数据可能有数千行表格。

所以如果我想在这个组件加载时调用store.dispatch(loadCourses()),它会去哪里?

【问题讨论】:

【参考方案1】:

您可能希望在组件的 componentDidMount() 生命周期方法中调用它。来自文档:

componentDidMount() 在组件安装后立即调用。需要 DOM 节点的初始化应该放在这里。如果您需要从远程端点加载数据,这是实例化网络请求的好地方。在此方法中设置状态将触发重新渲染。

https://facebook.github.io/react/docs/react-component.html#componentdidmount

【讨论】:

【参考方案2】:

如果您将组件中的操作作为道具获取并在需要时直接调用它们:

class CoursePage extends React.Component 
  constructor(props) 
    // ...
    this.handleClick = this.handleClick.bind(this) // available to click in component with proper scope set
  

  componentWillMount() 
    // called before component inits (only once)
    // this would be your first load, rather than calling it right
    // after you create your store
    this.props.loadCourses()
  

  handleClick() 
    // click handler
    this.props.loadCourses();
  

  // ...

  render() 
    // ... the rest of your component
     <button onClick=handleClick>Refresh data</button>
    // ... the rest of your component


【讨论】:

您希望避免使用componentWillMount() 生命周期方法来进行 API 调用、设置事件侦听器等。 我结合了你的两个答案,使用 componentDidMount 和上面的示例代码。这可以解决我的一个问题(在应用程序启动时没有加载所有内容),但它并没有解决我希望它会(并且没有提到)的另一个问题。我为每门课程都有一个嵌套组件(作者),在保存课程并重定向到课程列表视图后,给我一个作者对象的空值错误(显示列表中的名字和姓氏)。不过,这可能必须是另一篇文章…… 看起来你走在正确的轨道上。如果您还没有,我会阅读container vs presentational components。理想情况下,您不会在演示组件中进行任何数据获取。

以上是关于React + redux:连接组件加载时调用调度的主要内容,如果未能解决你的问题,请参考以下文章

来自根组件的 React/Redux 调度操作?

如何在页面加载时调度 redux 操作以在 useEffect 中加载数据

在 redux 中调度存储变量时,React 组件不会重新渲染

React/Redux - 在应用程序加载/初始化时调度操作

React + Redux:reducer 不会重新加载组件

Redux&React路由器:梳理调度和导航(history.push)