简单的 Redux 计数器组件实现

Simple Redux Counter Component implementation

我正在尝试使用简单的 Redux 实现计数器组件,使用 createStore 创建了 store 并使用了 store.dispatch

完整代码:

/*==================================================
This is only to format the code, I have used this editor, 
you can scroll down for the fiddle having error.
==================================================*/


 const createStore = Redux.createStore;

 const counter = (state = {
     counter: 0
 }, action) => {
     console.log('counter', state)
     switch (action.type) {
         case 'INCREMENT':
             return state.counter + 1;
         case 'DECREMENT':
             return state.counter - 1;
         default:
             return state;
     }
 }

 const store = createStore(counter);

 let Counter = React.createClass({
     getInitialState() {
         return store.getState()
     },

     incrementCounter() {
         store.dispatch({
             type: 'INCREMENT'
         });
     },
     decrementCounter() {
         store.dispatch({
             type: 'DECREMENT'
         });
     },

     render() {

         console.log('NEW STATE:', store.getState(), this.state)
         return (
              <div>
                <p>{this.state.counter}</p>
                <div>
                <button onClick={this.incrementCounter}>+</button>
                <button onClick={this.decrementCounter}>-</button>
                </div>
              </div>
      ) 
     }

 })

 ReactDOM.render( < Counter / > , document.getElementById('container'))
         
   

DEMO JSFIDDLE

我的问题:当我单击 incrementCounterdecrementCounter 函数时,我无法在渲染块中获取 更新的 存储值

您有几个问题

  1. 你需要订阅来改变状态,这很重要,因为你的组件不知道新状态
  2. stateObject,你必须 return 从 counter Object,在你的例子中你 return NumberINCREMENTDECREMENT

const createStore = Redux.createStore;

const counter = (state = {
  counter: 0
}, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return Object.assign({}, state, { counter: state.counter + 1 });
    case 'DECREMENT':
      return Object.assign({}, state, { counter: state.counter - 1 });
    default:
      return state;
  }
}

const store = createStore(counter);

let Counter = React.createClass({
  incrementCounter() {
    store.dispatch({ type: 'INCREMENT' });
  },
  
  decrementCounter() {
    store.dispatch({ type: 'DECREMENT' });
  },

  render() {
    return <div>
      <p>{ this.props.value }</p>
      <div>
        <button onClick={this.incrementCounter}>+</button>
        <button onClick={this.decrementCounter}>-</button>
      </div>
    </div> 
  }
})

const render = () => {
  ReactDOM.render(
    // get updated state value, and pass it to component
    <Counter value={ store.getState().counter } />, 
    document.getElementById('container')
  )
};

store.subscribe(render);
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>

注意:对于ReactReduxreact-redux)提供了名为Provider的组件,而你没有需要使用 store.subscribe,但在后台逻辑类似于我的示例

更新:

const { Provider, connect } = ReactRedux;
const { createStore, bindActionCreators } = Redux;

// Component 
let Counter = ({ value, onIncrement, onDecrement }) => (
  <div>
    <p>{ value }</p>
    <div>
      <button onClick={ onIncrement }>+</button>
      <button onClick={ onDecrement }>-</button>
    </div>
  </div> 
);

// Reducer
const counter = (state = {
  counter: 0
}, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, counter: state.counter + 1 };
    case 'DECREMENT':
      return { ...state, counter: state.counter - 1 };
    default:
      return state;
  }
}

// actions
const onIncrement = () => {
  return { type: 'INCREMENT' }
}

const onDecrement = () => {
  return { type: 'DECREMENT' }
};

// map state and actions
const mapStateToProps = (state) => {
  return {
    value: state.counter
  }
}

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators(
    { onIncrement, onDecrement }, 
    dispatch
  );
}

Counter = connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter);

const store = createStore(counter);

ReactDOM.render(
  <Provider store={ store }>
    <Counter />
  </Provider>,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.6/react-redux.js"></script>
<div id="container"></div>

你的主要问题是:

const counter = (state = {
     counter: 0
 }, action) => {
     console.log('counter', state)
     switch (action.type) {
         case 'INCREMENT':
             return state.counter + 1;
         case 'DECREMENT':
             return state.counter - 1;
         default:
             return state;
     }
 }

尤其是这一行:

         case 'INCREMENT':
             return state.counter + 1;
         case 'DECREMENT':
             return state.counter - 1;

你在return什么?一个号码!但是你的状态形状是一个对象{counter: Number}

所以你必须 return 一个像这样的新对象:

         case 'INCREMENT':
             return {counter: state.counter + 1}
         case 'DECREMENT':
             return {counter: state.counter - 1}

以上更改应该可以解决它。 为了在你的 reducer 中更加灵活,你应该像这样将新对象分配给现有状态:

         case 'INCREMENT':
             return {
                ...state,
                counter: state.counter + 1
             }
         case 'DECREMENT':
             return {
                ...state,
                counter: state.counter - 1
             }