Answer the question
In order to leave comments, you need to log in
How to fix a bug in your redux implementation?
Hello. I don't have my own implementation of redux (I'm tinkering with someone else's code). And I got the following problem.
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
// Начну по порядку. Ниже приведены функции createStore, connect, Provider
const createStore = (reducer, initialState) => {
let currentState = initialState
const listeners = []
const getState = () => currentState
const dispatch = action => {
currentState = reducer(currentState, action)
listeners.forEach(listener => listener())
}
const subscribe = listener => listeners.push(listener)
return { getState, dispatch, subscribe }
}
const connect = (mapStateToProps, mapDispatchToProps) =>
Component => {
class WrappedComponent extends React.Component {
render() {
return (
<Component
{...this.props}
{...mapStateToProps(this.context.store.getState(), this.props)}
{...mapDispatchToProps(this.context.store.dispatch, this.props)}
/>
)
}
componentDidUpdate() {
console.log('componentDidUpdate()')
this.context.store.subscribe(this.handleChange)
}
handleChange = () => {
console.log('handleChange')
this.forceUpdate()
}
}
WrappedComponent.contextTypes = {
store: PropTypes.object,
}
return WrappedComponent
}
class Provider extends React.Component {
getChildContext() {
return {
store: this.props.store,
}
}
render() {
return React.Children.only(this.props.children)
}
}
Provider.childContextTypes = {
store: PropTypes.object,
}
// Ниже приведены actions, action creators, reducers
// actions
const CHANGE_INTERVAL = 'CHANGE_INTERVAL'
// action creators
const changeInterval = value => ({
type: CHANGE_INTERVAL,
payload: value,
})
// reducers
const reducer = (state, action) => {
switch(action.type) {
case CHANGE_INTERVAL:
return {
...state,
currentInterval: state.currentInterval + action.payload
}
default:
return state
}
}
// Далее компонент, которые будет отрендерен
class IntervalComponent extends React.Component {
render() {
console.log('render()')
console.log(this.props)
return (
<div>
<span>Интервал обновления секундомера: {this.props.currentInterval} сек.</span>
<span>
<button onClick={() => this.props.changeInterval(-1)}>-</button>
<button onClick={() => this.props.changeInterval(1)}>+</button>
</span>
</div>
)
}
}
const Interval = connect((state) => ({
currentInterval: state,
// currentInterval: state.currentInterval,
}),
dispatch => ({
changeInterval: value => dispatch(changeInterval(value))
}))(IntervalComponent)
// init
ReactDOM.render(
<Provider store={createStore(reducer)}>
<Interval />
</Provider>,
document.getElementById('root')
)
const initialState = {
currentInterval: 3000
}
// reducers
const reducer = (state = initialState, action) => {
console.log('state', state)
console.log('action', action)
switch(action.type) {
case CHANGE_INTERVAL:
return {
...state,
currentInterval: state.currentInterval + action.payload
}
default:
return state
}
}
Answer the question
In order to leave comments, you need to log in
Redux dispatches the initial action the first time the store is created, passing undefined to the reducer and a special action {type: "INIT" }. The second point, I think the subscription to the store should be in componentDidMount, you can also add an unsubscribe from the store to componentWillUnmont to remove unnecessary cobacks.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question