Cannot change redux boolean state

时间:2018-09-18 20:25:49

标签: javascript reactjs redux react-redux state

I feel little confused, the problem is defineAvailableTouch action and state update connected to it.

Here is my code:

Actions/index.js

 import {
    ANIMATE_HELLO,
    HANDLE_SCROLL,
    IS_TOUCH_DEVICE,
    SET_ABOUT_TOP,
    SET_CONTACT_TOP,
    SET_PORTFOLIO_TOP
} from "../Constants/ActionTypes";

export const animateHello = hello => ({
    type: ANIMATE_HELLO,
    payload: hello
});

export const handleScroll = scrollDelta => ({
    type: HANDLE_SCROLL,
    payload: scrollDelta
});

export const defineTouchAvailable = isTouchDevice => ({
    type: IS_TOUCH_DEVICE,
    payload: isTouchDevice
});

export const setAboutTop = aboutTop => ({
    type: SET_ABOUT_TOP,
    payload: aboutTop
});

export const setContactTop = contactTop => ({
    type: SET_CONTACT_TOP,
    payload: contactTop
});

export const setPortfolioTop = portfolioTop => ({
    type: SET_PORTFOLIO_TOP,
    payload: portfolioTop
});

Reducers/index.js

 import {
    IS_TOUCH_DEVICE,
 } from "../Constants/ActionTypes";
 import { initialState } from "../Constants/InitialState/InitialState";

 export const rootReducer = (state = initialState, action) => {
     switch(action.type) {
          case ANIMATE_HELLO:
              return {
                  ...state,
                  hello: action.payload
              };
          case HANDLE_SCROLL:
              return {
                  ...state,
                  scrollState: action.payload
          };
          case IS_TOUCH_DEVICE:
             console.log(action.payload); //!!!!!! THIS PRINTS EXPECTED VALUE !!!!!!!!!!
             return {
                  ...state,
                  isTouchDevice: action.payload
          };
          case SET_ABOUT_TOP:
              return {
                   ...state,
                   aboutTop: action.payload
          };
          case SET_CONTACT_TOP:
              return {
                  ...state,
                  contactTop: action.payload
          };
          case SET_PORTFOLIO_TOP:
              return {
                  ...state,
                  portfolioTop: action.payload
              };
          default:
              return state
      }
 };

InitialState.js

export const initialState = {
    scrollState: 0,
    hello: 'H',
    aboutTop: 0,
    portfolioTop: 0,
    contactTop: 0,
    isTouchDevice: true
};   

App.js

import React, { Component } from 'react';
import { connect } from "react-redux";

import About from "./Containers/About";
import Contact from "./Containers/Contact";
import Page from "./Containers/Page";
import Projects from "./Containers/Projects";
import {
    defineTouchAvailable,
    handleScroll
} from "./Actions";

window.onbeforeunload = () => {
    handleScroll(0);
    document.documentElement.scrollTop = 0;
};

const mapStateToProps = state => {
    return {
        isTouchDevice: state.isTouchDevice
    }
};

const dispatchStateToProps = dispatch => {
    return {
        defineTouchAvailable: isTouchDevice => 
dispatch(defineTouchAvailable(isTouchDevice)),
        handleScroll: scrollState => dispatch(handleScroll(scrollState))
    }
};

class App extends Component {

    componentDidMount() {
        try {
            document.createEvent('touchevent');
            this.props.defineTouchAvailable(true);
        } catch(e) {
            this.props.defineTouchAvailable(false);
        }

        console.log(this.props.isTouchDevice); //!!!!!!!!!!!!!!! THIS ALWAYS PRINTS VALUE FROM initialState !!!!!!!!!!!!!!

        if(this.props.isTouchDevice) {
            document.documentElement.scroll(0, 1);
        }

        document.addEventListener('scroll', () => {
            if (document.documentElement.scrollTop === 0) {
                this.props.handleScroll(0);
            }
        });
    }

    render() {
        return (
            <div>
                <Page/>
                <Projects/>
                <About/>
                <Contact/>
            </div>
        );
    }
}

export default connect(mapStateToProps, dispatchStateToProps)(App);

I really can't figure out whats wrong here.

As I commented

  • reducer console.log prints correct value that is expected to be assigned to my state (isTouchDevice field), but

  • after assigning it in dispatch action nothing changes - it is always value from initialState.

Can someone please explain it to me? Do I change my redux state uncorrectly? Then why other actions work as they're expected to?

1 个答案:

答案 0 :(得分:0)

isTouchDevice的更新值将在componentDidUpdaterendercomponentWillReceiveProps中可用,而不在componentDidMount中可用。

componentDidMount仅在安装组件时被调用一次。

注意:不建议使用componentWillReceiveProps,最好不要使用它。