Реактивные компоненты не обновляются с магазином - PullRequest
0 голосов
/ 13 апреля 2020
Кнопка

. js компонент

    import React from "react"
import "../styles/button.scss"
import store from "../index"

class Button extends React.Component {
    constructor(props) {
        super(props)
        this.buttonTextChanger()
    }

    buttonTextChanger() {
        this.buttonText = "MainPage" === this.props.state.page ? "Az adatokhoz" : "A főoldalra"
    }


    logger = (actualPage) => {
        this.props.onButtonClick(actualPage)
        console.log("state from store before textchange", store.getState())
        console.log("state from props before textchange", this.props.state)
        this.buttonTextChanger()
    }

    render() {
        return (
            <div id="container">
                <button className="learn-more" onClick = {() => this.logger(this.props.state.page)}>
                    <span className="circle" aria-hidden="true">
                    <span className="icon arrow"></span>
                    </span>
                    <span className="button-text">{this.buttonText}</span>
                </button>
            </div>
        )
    }
}

export default Button

Моя проблема в том, что реквизиты компонента, по-видимому, не обновляются в хранилище избыточностей. После того, как функция onClick запустится, хранилище приставок обновится до правильного значения, mapStateToProps также будет работать с правильным состоянием, и после этого, если я попытаюсь зарегистрировать состояние из реквизита, получу старое значение. Если я делаю тот же журнал в функции рендеринга перед возвратом JSX, я получаю правильное состояние от реквизита, и я не могу понять, почему оно не обновляется сразу после того, как хранилище избыточностей. Поэтому, если я изменю код на следующий, он будет работать как положено:

logger = (actualPage) => {
        this.props.onButtonClick(actualPage)
        console.log("state from store before textchange", store.getState())

    }

    render() { 
        console.log("state from props before textchange", this.props.state)
        this.buttonTextChanger()  
        return (
            <div id="container">
                <button className="learn-more" onClick = {() => this.logger(this.props.state.page)}>
                    <span className="circle" aria-hidden="true">
                    <span className="icon arrow"></span>
                    </span>
                    <span className="button-text">{this.buttonText}</span>
                </button>
            </div>
        )
    }
}

Функция редуктора

import { combineReducers } from "redux"

export const changePageReducer = (state = {page : "MainPage"}, action) => {
    if (action.type === "CHANGE_PAGE")
        if (action.payload !== state.page) {
            return action.payload
        }

    return state.page
}

export const combinedReducers = combineReducers({page : changePageReducer})

Контейнер кнопок

import { connect } from "react-redux"
import Button from "../components/Button"
import changePage from "../actions/changePage"

const mapStateToProps = (state) => {
    console.log("az injectelt state", state)
    return {state}
} 

const mapDispatchToProps = (dispatch) => {
    return {
        onButtonClick : (page) => {
            switch (page) {
                case "MainPage":
                    dispatch(changePage("DataPage"))
                    break
                case "DataPage":
                    dispatch(changePage("MainPage"))
                    break
                default:
                    dispatch(changePage("MainPage"))
            }
        }
    }
}

const ChangePageContainer = connect(mapStateToProps, mapDispatchToProps)(Button)

export default ChangePageContainer

Но я бы хотел для извлечения вызова функции buttonTextChanger () из функции рендеринга и вызова ее по щелчку.

TLDR: проблема:

logger = (actualPage) => {
  console.log("prop state value before dispatch", this.props.state)
  console.log("store value before dispatch", store.getState())
  this.props.onButtonClick(actualPage)
  console.log("prop state value after dispatch", this.props.state)
  console.log("store value after dispatch", store.getState())
}

также есть файл console.log в функции mapStateToProps для увидеть состояние, которое передается реквизита. Это дает:

prop state value before dispatch {page: "MainPage"}
store value before dispatch {page: "MainPage"}
state when mapStateToProps function called {page: "DataPage"}
store value after dispatch {page: "DataPage"}
prop state value after dispatch {page: "MainPage"}

Таким образом, опора не обновляется.

1 Ответ

2 голосов
/ 13 апреля 2020

Итак, вы не можете понять, почему this.props.state не обновляется даже после вызова диспетчера?

Видите ли, Redux полностью построен на функциональном программировании , и теперь с перехватами React также полностью движется в сторону функционального программирования, черт возьми, даже JavaScript изначально был построен как функциональное программирование.

Одна вещь, которая полностью отличается от OOP, и самая крутая вещь в том, что В функциональном программировании нет мутаций. Нет. Vanilla Redux полностью FP, имеет только чистые функции - функции без побочных эффектов. Вот почему вам нужна Redux Saga или другая библиотека для выполнения вызовов API - нечистых функций.

Обрезка до погони,

logger = (actualPage) => {
  // here,
  // actualPage => new value
  // this.props.state => old value
  // they will remain as such throughout this function


  console.log("prop state value before dispatch", this.props.state)
  console.log("store value before dispatch", store.getState())
  this.props.onButtonClick(actualPage)

  // even if you update the Redux Store, 
  // `this.props.state` will still have the old value
  // since this value will not be mutated

  console.log("prop state value after dispatch", this.props.state)
  console.log("store value after dispatch", store.getState())
}

Тогда как насчет store.getState(), их значения обновленный , вы можете спросить.

Обратите внимание, что это не store.getState, а вместо store.getState()? Да, это функция, а не значение. Всякий раз, когда вы вызываете их, они возвращают последнее значение, и в них нет никаких мутаций. В вашем случае, во второй раз, когда вы звоните после отправки действия, следовательно, вы получите последнее значение. Это не мутация, store.getState() просто взял последнее значение и вернул его вам. logger() получит новые значения после завершения первого вызова, затем цикл повторяется снова.

Диспетчеры действий создадут новый state из старого state, поэтому вы можете путешествовать во времени в Redux DevTools.

Снова повторение

logger = (actualPage) => {
  // old value
  console.log("prop state value before dispatch", this.props.state)
  // old value
  console.log("store value before dispatch", store.getState())

  // new value
  this.props.onButtonClick(actualPage)
  // redux would be updated with new values by now

  // but still old value - no mutation
  console.log("prop state value after dispatch", this.props.state)
  // new value
  console.log("store value after dispatch", store.getState())
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...