Всем привет. У меня не есть самостоятельная реализация redux (разбираюсь с чужим кодом). И у меня возникла следующая проблема.
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')
)
В данном примере очевидная проблема, что не передается initialState
Что сделал я: в reducer дописал: state = initialState, ну и конечно описал initialState
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
}
}
Остались две проблемы:
- initialState нет при инициализации компонента
- И когда reducer обновляет состояние, не происходит render IntervalComponent, соответственно визуально ничего не меняется.
Буду благодарен любой помощи.
https://codepen.io/gsdev99/pen/pYqmRr