用connect连接react组件和redux怎么理解

这块代码看好久没懂,求解。

redux action、store、reducer差不多理解,但是不知道这块代码有什么用,为什么这么写?

原文链接 https://segmentfault.com/a/11...

clipboard.png

阅读 6.5k
2 个回答

1、关于mapStateProps(),注释上说是声明当前组件有关系的state的属性。无论是小型还是大型应用中,state数都是一颗体积庞大的树,会有各种组件的state属性组成,mapStateProps的作用就是只绑定当前组件相关的state属性,这样可以保证避免传入额外的state属性进来。

function mapStateProps(state) {
    return { text: state.text } //传入单一的属性
    //return state.login   //传入当前组件的所有属性
    //return state //传入所有的state属性
}

2、然后我们再看看dispatch,上面state的作用是从组件读取state属性,那么dispatch的作用就是组件告诉action它想要做什么事情,action就找到对应的函数去执行。

比如组件想要改变text的内容,就通过dispatch方法告诉action:喂,action,我不喜欢这句话,赶紧给我换一句显示!!

action收到之后就很听话,马上告诉reducer去更新text,更新text之后,组件就可以接收到新的state属性值了。

function mapDispatchToProps(dispatch) {
//这个函数的意思就是告诉组件要绑定的action方法,不然组件是不知道该告诉谁去执行text的更新的。
//组件 =》(dispatch:告诉)=》action 
    return {
        actions: bindActionCreators({changeText: cahngeText, buttonClick: buttonClick}, dispatch)
    }
}

3、最后一行代码:App = connect(mapStateToProps, mapDispatchToProps)(App)
上面定义的关联state和action的方法需要绑定到当前组件上面,这句代码的作用就是这个。不指定绑定的组件,万一跑到其他组件去了怎么办呢??

4、我通常不这么写,我的写法是下面这种,意思是一样的

@connect(
    state => state.text
    dispacth => bindActionCreators({...actions}, dispatch)
)
export default class App extends Component {

}

5、so,你喜欢怎么写就怎么写。

首先你要知道React组件的state和props的区别,然后redux的store就是一个巨大的外部状态,connect就是把这个状态和react组件的props关联起来。(先不考虑dispatch,原理是一样的)

如果你会typescript就更好理解了,以经典的计数器组件为例,没有redux的时候,你要自己维护状态(state):

interface OwnProps {} // 自己没有props
interface OwnState {  // 自己维护了状态
    count: number
}

class Counter extends React.Component<OwnProps , OwnState> {

    constructor() {
        super();
        this.state = {count: 0}
    }
    render () {
        return <h1>Count: {this.state.count}</h1>;
    }
}

当你把状态移到redux,组件可以就不自己维护状态了:

interface OwnProps {} // 自己的props,没东西
interface OwnState {} // 自己维护的状态,没东西
interface ConnectedState {  // 从redux传来的状态
    count: number
}
type CounterProps = ConnectedState & OwnProps; // 实际的props是自己的props加上从redux传来的状态的结合

class Counter extends React.Component<CounterProps, OwnState> {

    render () {
        return <h1>Count: {this.props.count}</h1>;
    }
}

上面应该很好理解,那么connect怎样把redux的状态传给到组件呢,通过自定义的函数把redux的state映射(map)到合适的格式(类型),然后把组件包装起来:

// mapStateToProps就是把state映射到ConnectedState(从redux传来的状态)
const mapStateToProps = (state: State, ownProps: OwnProps): ConnectedState => ({
    count: state.counter.count
});

// connect根据映射函数,从redux的取数据,然后用一个组件把Counter包起来,把数据传给Counter
// 返回的ConnectedCounter类型是 eact.Component<OwnProps, OwnState>
// 因为ConnectedState已经通过redux和connect拿到了
const ConnectedCounter = connect(mapStateToProps)(Counter);

// 导出ConnectedCounter而不是Counter
export default ConnectedCounter;

就使用来说,你只要知道connect是把redux的状态和action传到组件就可以了。

更进一步,你可以看connect的函数签名(简化版):

type ComponentClass<P> = React.ComponentClass<P>; // ComponentClass就是一个React组件

// ComponentDecorator是个函数,参数类型是ComponentClass<TOriginalProps>,返回值类似是ComponentClass<TOwnProps>
// 就是把原来props为TOriginalProps的component变成props为TOwnProps的组件。
interface ComponentDecorator<TOriginalProps, TOwnProps> {
    (component: ComponentClass<TOriginalProps>): ComponentClass<TOwnProps>;
}

// MapStateToProps是个函数,把任意类型的state和TOwnProps组合成TStateProps
interface MapStateToProps<TStateProps, TOwnProps> {
    (state: any, ownProps?: TOwnProps): TStateProps;
}

// connect有一个参数mapStateToProps,mapStateToProps可以把state和TOwnProps转成TStateProps,state肯定是connect传过来的。
// connect返回一个ComponentDecorator,ComponentDecorator又把props为TStateProps的组件转回props为TOwnProps的组件(因为TStateProps已经从redux里拿到了,最后还需要自己传的props就是TOwnProps)
function connect<TStateProps, TDispatchProps, TOwnProps>(
    mapStateToProps: MapStateToProps<TStateProps, TOwnProps>
): ComponentDecorator<TStateProps, TOwnProps>;

看懂上面的函数签名,不看react-redux的代码都知道connect是做什么的。

1 篇内容引用
推荐问题
宣传栏