简单的 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'))
我的问题:当我单击 incrementCounter
和 decrementCounter
函数时,我无法在渲染块中获取 更新的 存储值
您有几个问题
- 你需要订阅来改变状态,这很重要,因为你的组件不知道新状态
state
是 Object
,你必须 return 从 counter
Object
,在你的例子中你 return Number
在 INCREMENT
和 DECREMENT
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>
注意:对于React
,Redux
(react-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
}
我正在尝试使用简单的 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'))
我的问题:当我单击 incrementCounter
和 decrementCounter
函数时,我无法在渲染块中获取 更新的 存储值
您有几个问题
- 你需要订阅来改变状态,这很重要,因为你的组件不知道新状态
state
是Object
,你必须 return 从counter
Object
,在你的例子中你 returnNumber
在INCREMENT
和DECREMENT
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>
注意:对于React
,Redux
(react-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
}