React.js - 递增状态对象值

时间:2016-11-29 14:15:48

标签: javascript reactjs redux

我有一个州'用户',其中包含用户列表。我想在点击时增加用户值“count”,初始“count”值为1.行为应该是:您有一个用户列表,在点击特定用户后,您将被重定向到/ userdetail /:user_twitter_name您可以在其中单击“投票给用户”按钮,该按钮将增加user.count值+ = 1,在第一次运行中从1增加到2。

  /* actions/counter.js */

    export function userVoted(user) {
      return {
        type: 'USER_VOTED',
        payload: user.count
      };
    }

      
    /* reducers/reducer_user_vote.js */
      
    export default function(state = null, action) {
      switch(action.type) {
      case 'USER_VOTED':
          return (action.payload + 1);
      }
      return state;
    }


    /* reducers/index.js */
      
    import { combineReducers } from 'redux';
    import UserReducer from './reducer_user';
    import ActiveUser from './reducer_active_user';
    import userVoted from './reducer_user_vote';

    const rootReducer = combineReducers({
      users: UserReducer,
      activeUser: ActiveUser,
      userVoted: userVoted
    });


    /* reducers/reducer_user.js */

    export default function () {
      return [
        {username: 'John Doe', email: 'john@doe.com', twitter: 'johndoe1', count: 1},
        {username: 'Paul Smith', email: 'smith.paul@csswizardry.com', twitter: 'csswizardry', count: 1},
        {username: 'Petra Tweets', email: 'petra@tweets.me.com', twitter: 'petra', count: 1},
        {username: 'Mark Chills', email: 'chillmark@company.com', twitter: 'chillymark12', count: 1},
        {username: 'John McIntyre', email: 'comic@mcintyre.com', twitter: 'jokesforfun', count: 1},
      ];
    }
        

    export default rootReducer;


    /* components/seconddetail.js */


    import React, { Component } from 'react';
    import { connect } from 'react-redux';
    import { Router, Link } from 'react-router';
    import { userVoted } from '../actions/counter';
    import { bindActionCreators } from 'redux';



    class SecondDetail extends Component {


      render() {

        if (!this.props.params.twitter) {
          return <div>Select a user to view details.</div>;
        }

        // Filtered User that matches the URL param
        const filteredUser = this.props.users.filter((user) => {
          if (user.twitter == this.props.params.twitter) {
            return user;
          }
        });

        const resultUser = filteredUser[0];

        return (
          <div className="detail">
            <h2 className="text-center">Details:</h2>
            <br />
            <div className="row">
              <div className="col-xs-12 col-md-3 text-center">
                <i className="fa fa-user fa-4x"></i>
                <br/>
                {resultUser.username}
              </div>
              <div className="col-xs-12 col-md-3 text-center">
                <i className="fa fa-envelope-o fa-4x"></i>
                <br/>
                {resultUser.email}
              </div>
              <div className="col-xs-12 col-md-3 text-center">
                <i className="fa fa-twitter fa-4x"></i>
                <br/>
                {resultUser.twitter}
              </div>
              <div className="col-xs-12 col-md-3 text-center">
                <i className="fa fa-star fa-4x"></i>
                <br/>
                {resultUser.count}
              </div>
            </div>
            <br />
            <br />
            <div className="row">
              <div className="col-xs-12 text-center">
                  <div className="btn btn-success" onClick={() => this.props.userVoted(resultUser)}>Vote for user</div>
                  <br />
                  <br />
                  <Link to={'/'} className="btn btn-primary">Home</Link>
              </div>
            </div>
          </div>
        );
      }
    }

    function mapStateToProps(state) {
      return {
        users: state.users
      };
    }

    function mapDispatchToProps(dispatch) {
      return bindActionCreators({ userVoted }, dispatch);
    }

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

    /* index.js */

    
    import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, Route, Link, browserHistory } from 'react-router';

import App from './components/app';
import DetailComponent from './components/detailcomponent';
import SecondDetail from './components/seconddetail';
import reducers from './reducers';

const createStoreWithMiddleware = applyMiddleware()(createStore);

ReactDOM.render(
    <Provider store={createStoreWithMiddleware(reducers)}>
      <Router history={browserHistory}>
        <Route path="/" component={App} />
        <Route path="/detail" component={DetailComponent} />
        <Route path="/userdetail/:twitter" component={SecondDetail} />
      </Router>
    </Provider>
  , document.querySelector('.container'));

但是,在项目单击时,函数被调用(我可以在函数内部的console.log()时看到控制台中的值),但不会增加特定用户的值。你能告诉我吗?非常感谢

1 个答案:

答案 0 :(得分:0)

我无法看到所有代码,但看起来状态是:

{
  users: UserReducer,
  activeUser: ActiveUser,
  userVoted: userVoted
}

渲染函数中,您将计数呈现为 resultUser.count 但我无法在任何reducer中看到此更新。 (我可以看到用户投票减速器更新状态的 userVoted 部分(整数?))。如果 userVoted 是一个整数,您如何知道它适用于哪个用户?

因此,您可能需要修改 mapStateToProps ,以便您可以更新每个用户的计数,或者实际修改您的状态。

修改

继续下面的评论;如果你想直接在userReducer中更新用户数,你可以使用下面的逻辑(它需要将'USER_VOTED'动作放入reducer的switch语句中),下面的代码只是为了说明如何修改用户数组:

var state = [
        {username: 'John Doe', email: 'john@doe.com', twitter: 'johndoe1', count: 1},
        {username: 'Paul Smith', email: 'smith.paul@csswizardry.com', twitter: 'csswizardry', count: 1},
        {username: 'Petra Tweets', email: 'petra@tweets.me.com', twitter: 'petra', count: 1},
        {username: 'Mark Chills', email: 'chillmark@company.com', twitter: 'chillymark12', count: 1},
        {username: 'John McIntyre', email: 'comic@mcintyre.com', twitter: 'jokesforfun', count: 1},
      ];


var action = {
    type:  'USER_VOTED',
    user:  {username: 'Mark Chills', email: 'chillmark@company.com', twitter: 'chillymark12', count: 1}
};

var newState = state.map(u => {
  return action.user.username === u.username ? Object.assign({}, u, { count: u.count + 1} ) : u;
});



console.log(newState);

注意我必须在用户名中匹配,这意味着这必须是唯一的, id 会更好。