0

I seen 2 ways of doing the same thing but I am not sure what is the proper way.

Component

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

Or

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

The first way uses 2 different functions mapStateToProps() and matchDispatchToProps() while the other way uses @connect(....).

When I use the @connect I get a whole bunch of warnings saying that it has not been finalized and might change.

chobo2
  • 83,322
  • 195
  • 530
  • 832

3 Answers3

1

I think the first method will give you less problems in the end. Someone else can chime in though too.

  • This isn't really an answer - can you add some detail about what makes the first method better? Any references to docs or some performance tests...? – brichins Aug 08 '16 at 18:30
1

The @ symbol is a decorator which is still considered experimental. So I would use that at your own risk. Your first code block is the safer way to do it as described in the official docs. Both blocks essentially do the same thing but decorators are more sugar than anything.

References:

Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
Jackson
  • 139
  • 2
  • 5
0

The answer by Jackson is right in every sense however he is missing out the importance of using the first version for the usage of unit testing. If you want to be able to unit test a component (which usually means testing with the unconnected version) you need to be able to export the connected and unconnected component.

Using your example and assuming you are using jest/enzyme you could do something like this:

// 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')
  });
});

Once you build larger projects being able to unit test will provide sanity to your coding life. Hope this helps