我应该在Redux中使用哪种方式连接器?

时间:2016-08-08 18:05:55

标签: reactjs redux

我看到了两种做同样事情的方法,但我不确定什么是正确的方法。

组件

import React, {Component} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {selectUser} from '../actions/index'


class UserList extends Component {

    renderList() {
        return this.props.users.map((user) => {
            return (
                <li
                    key={user.id}
                    onClick={() => this.props.selectUser(user)}
                >
                    {user.first} {user.last}
                </li>
            );
        });
    }

    render() {
        return (
            <ul>
                {this.renderList()}
            </ul>
        );
    }

}

// Get apps state and pass it as props to UserList
//      > whenever state changes, the UserList will automatically re-render
function mapStateToProps(state) {
    return {
        users: state.users
    };
}

// Get actions and pass them as props to to UserList
//      > now UserList has this.props.selectUser
function matchDispatchToProps(dispatch){
    return bindActionCreators({selectUser: selectUser}, dispatch);
}

// We don't want to return the plain UserList (component) anymore, we want to return the smart Container
//      > UserList is now aware of state and actions
export default connect(mapStateToProps, matchDispatchToProps)(UserList);

https://github.com/buckyroberts/React-Redux-Boilerplate

或者

import React from "react"
import { connect } from "react-redux"

import { fetchUser } from "../actions/userActions"
import { fetchTweets } from "../actions/tweetsActions"

@connect((store) => {
  return {
    user: store.user.user,
    userFetched: store.user.fetched,
    tweets: store.tweets.tweets,
  };
})
export default class Layout extends React.Component {
  componentWillMount() {
    this.props.dispatch(fetchUser())
  }

  fetchTweets() {
    this.props.dispatch(fetchTweets())
  }

  render() {
    const { user, tweets } = this.props;

    if (!tweets.length) {
      return <button onClick={this.fetchTweets.bind(this)}>load tweets</button>
    }

    const mappedTweets = tweets.map(tweet => <li>{tweet.text}</li>)

    return <div>
      <h1>{user.name}</h1>
      <ul>{mappedTweets}</ul>
    </div>
  }
}

https://github.com/learncodeacademy/react-js-tutorials/tree/master/5-redux-react

第一种方式使用2个不同的函数mapStateToProps()matchDispatchToProps(),而另一种方式使用@ connect(....).

当我使用@connect时,我收到一大堆警告,说它尚未最终确定并且可能会发生变化。

3 个答案:

答案 0 :(得分:1)

我认为第一种方法最终会给你带来较少的问题。其他人也可以插话。

答案 1 :(得分:1)

@符号是装饰者,仍然被认为是实验性的。所以我会自己冒风险使用它。您的第一个代码块是更安全的方式,如官方文档中所述。两个块基本上都做同样的事情,但装饰器比任何东西都更多糖。

参考文献:

答案 2 :(得分:0)

杰克逊的答案在任何意义上都是正确的,但是他错过了使用第一个版本进行单元测试的重要性。如果您希望能够对组件进行单元测试(通常意味着使用未连接的版本进行测试),则需要能够导出已连接和未连接的组件。

使用你的例子并假设你正在使用jest / enzyme,你可以这样做:

// notice importing the disconnected component
import { UserList } from '../relative/file/path/UserList'
import { mount } from 'enzyme'

describe('UserList', () => {
  it('displays the Username', () => {
    const users = [{fist: 'Person', last: 'Thing'}, ... ]
    const UserList = mount(<UserList users={users} />)

    export(UserList.find('li')[0].text()).toEqual('Person Thing')
  });
});

一旦你建立了更大的项目,能够进行单元测试将为你的编码生活提供理智。希望这有帮助

相关问题