全方位解读 react-redux 的 connect 方法

作为一名前端开发者,在开发过程中难免会使用到 react-redux 库来处理组件之间的数据流转,而 connect 方法作为 react-redux 中最重要的一部分,其作用就是连接组件和 redux 的 store,协助组件轻松获取到所需的 state 和 dispatch。本文将全方位解读 connect 方法,包括使用方法、原理解析以及常见应用场景,希望能对大家有所帮助。

使用方法

在 react-redux 中,我们可以通过以下方式引入 connect 方法:

import { connect } from 'react-redux';

connect 方法接收两个参数,其中 mapStateToProps 和 mapDispatchToProps 是可选的,如果省略,则默认将 store 中的 state 和 dispatch 作为 props 传入组件中。具体用法如下:

connect(mapStateToProps?, mapDispatchToProps?)(
  WrappedComponent
);

原理解析

connect 方法的作用主要是将组件与 store 进行连接,为组件提供 state 和 dispatch 两个对象。其实现原理主要分为三步:

第一步:创建一个容器组件

connect 方法创建的就是一个容器组件,它会接收 WrappedComponent 作为参数,然后通过 React.createElement() 方法将 WrappedComponent 包装在容器组件中,使之成为容器组件的子组件。

第二步:将 state 映射为 props

第二步是将 store 中的 state 映射为 props,通过 mapStateToProps 函数来完成。它接收一个 state 参数,然后返回一个对象,其中的 key-value 对应的就是 WrappedComponent 中需要的 props。

const mapStateToProps = state => {
  return {
    todos: state.todos
  };
}

第三步:将 dispatch 映射为 props

第三步是将 store 中的 dispatch 映射为 props,通过 mapDispatchToProps 函数来完成。它接收一个 dispatch 参数,然后返回一个对象,其中的 key-value 对应的就是 WrappedComponent 中需要的 props。

const mapDispatchToProps = dispatch => {
  return {
    addTodo: todo => dispatch(addTodoAction(todo)),
    toggleTodo: id => dispatch(toggleTodoAction(id)),
    deleteTodo: id => dispatch(deleteTodoAction(id))
  };
}

通过以上三个步骤,connect 方法最终会形成一个新的组件,它将 oldProps 和新的 state 和 dispatch 合并成一个新的 props,从而达到连接组件和 store 的目的。

常见应用场景

connect 方法适用于许多场景,下面介绍常见的几种应用场景。

基本使用

import { connect } from 'react-redux';

const mapStateToProps = state => {
  return {
    count: state.count
  };
}

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch({ type: 'INCREMENT' }),
    decrement: () => dispatch({ type: 'DECREMENT' }),
  };
}

class Counter extends React.Component {
  render() {
    const { count, increment, decrement } = this.props;

    return (
      <div>
        <p>{count}</p>
        <button onClick={increment}>+</button>
        <button onClick={decrement}>-</button>
      </div>
    );
  }
}

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

高阶组件

function withAuth(WrappedComponent) {
  class WithAuth extends React.Component {
    render() {
      const { isAuthenticated } = this.props;

      if (isAuthenticated) {
        return <WrappedComponent {...this.props} />;
      } else {
        return <Redirect to='/login' />;
      }
    }
  }

  const mapStateToProps = state => {
    return {
      isAuthenticated: state.isAuthenticated
    };
  }

  return connect(mapStateToProps)(WithAuth);
}

export default withAuth(MyComponent);

多个 connect 嵌套

const mapStateToProps = state => {
  return {
    count: state.count
  };
}

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch({ type: 'INCREMENT' }),
    decrement: () => dispatch({ type: 'DECREMENT' }),
  };
}

const withCounter = connect(mapStateToProps, mapDispatchToProps);

const mapStateToProps2 = state => {
  return {
    todos: state.todos
  };
}

const mapDispatchToProps2 = dispatch => {
  return {
    addTodo: todo => dispatch({ type: 'ADD_TODO', todo }),
    toggleTodo: id => dispatch({ type: 'TOGGLE_TODO', id }),
    deleteTodo: id => dispatch({ type: 'DELETE_TODO', id })
  };
}

const withTodos = connect(mapStateToProps2, mapDispatchToProps2);

class MyComponent extends React.Component {
  render() {
    const { count, increment, decrement, todos, addTodo, toggleTodo, deleteTodo } = this.props;

    return (
      <div>
        <Counter count={count} increment={increment} decrement={decrement} />
        <TodoList todos={todos} addTodo={addTodo} toggleTodo={toggleTodo} deleteTodo={deleteTodo} />
      </div>
    );
  }
}

export default withCounter(withTodos(MyComponent));

总结

通过全方位解读,我们可以看到 connect 方法真正的作用其实就是返回一个高阶组件,它将 store 的 state 和 dispatch 映射到组件的 props 中,从而让组件轻松获得所需的数据。在我们日常开发中,合理地运用 connect 方法可以大幅减少组件之间的耦合度,提高代码的可维护性和可扩展性,相信这些技巧和实践对于大家来说一定有很大的指导意义。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a34078add4f0e0ffb5d0d6


纠错反馈