Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 11.08.2019, 07:26
Аспирант
Отправить личное сообщение для gsdev99 Посмотреть профиль Найти все сообщения от gsdev99
 
Регистрация: 03.02.2019
Сообщений: 72

Как исправить ошибку в своей реализации redux?
Всем привет. У меня не есть самостоятельная реализация 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

Последний раз редактировалось gsdev99, 11.08.2019 в 14:58.
Ответить с цитированием
  #2 (permalink)  
Старый 13.08.2019, 08:04
Аватар для SuperZen
Профессор
Отправить личное сообщение для SuperZen Посмотреть профиль Найти все сообщения от SuperZen
 
Регистрация: 08.11.2017
Сообщений: 642

const initialState =  {
currentInterval:  3000
}

const createStore = (reducer, initialState) => {
  let currentState = initialState
  const listeners = []
  
  console.log('currentState', currentState)
  

  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)}
          />
        )
      }
      
      componentDidMount() {
        console.log('WRAPPEDCOMPONENT DID MOUNT')
        this.context.store.subscribe(this.handleChange)
      }

//      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() {
    console.log('getChildContext, store', this.props.store)
    return {
      store: this.props.store,
    }
    
  }

  render() {
    return React.Children.only(this.props.children)
  }
  
  
}

Provider.childContextTypes = {
    store: PropTypes.object,
  }


// actions

const FETCH_INITIAL_STATE = 'FETCH_INITIAL_STATE'
const CHANGE_INTERVAL = 'CHANGE_INTERVAL'

// action creators
const fetchInitialState = () => ({
  type: FETCH_INITIAL_STATE
})

const changeInterval = value => ({
  type: CHANGE_INTERVAL,
  payload: value,
})

// reducers
const reducer = (state, action) => {
  console.log('state', state)
  console.log('action', action)

  switch (action.type) {

    case FETCH_INITIAL_STATE:
      return state

    case CHANGE_INTERVAL:
      
      console.log('CHANGE_INTERVAL', state, action)
      
      const nextState = {
        ...state,
        currentInterval: state.currentInterval + action.payload,
      }
      
      console.log('nextState', nextState, 'ok')
      
      return nextState

    default:
      return state
  }
}

// components

class IntervalComponent extends React.Component {

  componentDidMount() {
    console.log('componentDidMount()')
    this.props.fetchInitialState()

    console.log('props', this.props)
  }

  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,
    // currentInterval: state.currentInterval,
  }),
  dispatch => ({
    changeInterval: value => dispatch(changeInterval(value)),
    fetchInitialState: value => dispatch(fetchInitialState()),
  }))(IntervalComponent)

const str = createStore(reducer, initialState)

// init
ReactDOM.render(
  <Provider store={str}>
    <Interval/>
  </Provider>,
  document.getElementById('root')
)


) что-то получилось...

1) inititalState ты не правильно передавал, тк createStore уже ждет initialState
2) потом неправильный объект был
3) и напоследок, не там стоял подписчик...
Ответить с цитированием
  #3 (permalink)  
Старый 13.08.2019, 17:34
Аспирант
Отправить личное сообщение для gsdev99 Посмотреть профиль Найти все сообщения от gsdev99
 
Регистрация: 03.02.2019
Сообщений: 72

Спасибо тебе большое!
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не могу понять как убрать синтаксическую ошибку oleg901 Элементы интерфейса 10 01.08.2019 18:43
Как обработать ошибку несколько раз и создать исключение? jtag Общие вопросы Javascript 2 18.12.2017 14:39
Как исправить ошибку «No 'Access-Control-Allow-Origin' header...» при аплоадинге карт femalemoustache Общие вопросы Javascript 4 29.06.2017 11:53
Необходимо найти и исправить ошибку в CSS/Javascript javascript_pupil Работа 1 02.05.2011 15:41
Как получиться доступ к элементам не своей страницы? AlkaLoiD Общие вопросы Javascript 4 29.11.2010 12:47