React + Redux-状态更改后组件不会更新

时间:2019-08-25 10:07:03

标签: reactjs redux

嗨,我有一个React + Redux应用程序。它由标题和登录表单组成。用户成功登录后,我希望注销按钮显示在标题中。但是现在看来,在登录操作发生之前,除非我未显示刷新页面注销按钮,否则react渲染头会出现。

我的登录表格

class LoginForm extends React.Component {

    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleSubmit = (e, {setFieldError, setSubmitting}) => {
        const {username, password} = e;
        if (username && password) {
            loginService
                .login(username, password)
                .then(
                    success => {
                        const data = success.data;
                        if (success.status === 200 && data.success === true) {
                            return {...data.user, password: password};
                        } else if (success.status === 400) {
                            window.location.reload();
                        }
                        const error = (!data.success && "Wrong credentials") || success.statusText;
                        return Promise.reject(error);
                    }
                )
                .then(
                    auth => {
                        this.props.login(auth)
                    },
                    error => {
                        if (error.response.status === 400) {
                            setFieldError("username", "Zły login lub hasło");
                            setFieldError("password", "   ");
                            setSubmitting(false);
                        }
                    }
                )
        }
    };

    render() {
        return (
            <Formik ...
        )
}


function mapState(state) {
    const {session} = state;
    return {session}
}

const connectedLoginForm = connect(mapState, {login: loginActions.login})(LoginForm);
export {connectedLoginForm as LoginForm};

在用户按下登录按钮后调度的我的登录操作

export const loginActions = {
    login
};

function login(data) {
    const session = {
        id: data.id,
        username: data.email,
        password: data.password
    };
    loginService.saveSessionData(session);
    return dispatch => {
        dispatch({type: loginConstants.LOGGED_IN, payload: session});
        history.push('/');
    }
}

我的登录减少器

const session = loginService.getSessionData();
const initialState = session ? {session} : {};

export function login(state = initialState, action) {
    if (action.type === loginConstants.LOGGED_IN) {
        return {
            session: action.payload
        };
    } else {
        return state
    }
}

我的标题类显示不正确

class Header extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isLogged: this.props.isLogged,
            showText: true
        };
        this.updatePredicate = this.updatePredicate.bind(this);
    };

    componentDidMount() {
        this.updatePredicate();
        window.addEventListener("resize", this.updatePredicate);
    }

    componentWillUnmount() {
        window.removeEventListener("resize", this.updatePredicate);
    }

    updatePredicate() {
        this.setState({showText: window.innerWidth > 319});
    }

    render() {
        return (
            <MDBNavbar color="white" light expand="md" className={'mt-0'} style={{marginTop: "0px"}} fixed={'top'}>
                <MDBNavbarBrand href={'/'}>
                    <img alt="Logo" src={logo} width="30" height="30" className="d-inline-block align-top"/>
                    <strong id="app-name">
                        {AppName}
                    </strong>
                </MDBNavbarBrand>
                {this.state.isLogged &&
                <MDBNavbarNav right>
                    <MDBNavItem>
                        <MDBNavLink to="/logout">
                            <MDBIcon icon="sign-out-alt"/>
                            {this.state.showText && <span>Wyloguj się</span>}
                        </MDBNavLink>
                    </MDBNavItem>
                </MDBNavbarNav>
                }
            </MDBNavbar>
        );
    }
}

function mapState(state) {
    const {session} = state.login;
    return {isLogged: !(typeof session === 'undefined')}
}

const connectedHeader = connect(mapState)(Header);
export {connectedHeader as Header};

可能是什么原因?

1 个答案:

答案 0 :(得分:2)

constructor仅执行一次,因此,当您设置isLogged时,

this.state = {
   isLogged: this.props.isLogged,
   showText: true
};

isLogged在收到下一个道具时不会改变。

您在这里有两种方法。

  1. 最简单的一种是直接使用this.props.isLogged来满足您的条件,
{this.props.isLogged &&
    <MDBNavbarNav right>
        <MDBNavItem>
            <MDBNavLink to="/logout">
                <MDBIcon icon="sign-out-alt"/>
                {this.state.showText && <span>Wyloguj się</span>}
            </MDBNavLink>
        </MDBNavItem>
    </MDBNavbarNav>
}
  1. 另一种方法是使用componentDidUpdate接收新道具时手动更新状态
componentDidUpdate(nextProps){
  if(nextProps.isLogged !== this.props.isLogged){
     this.setState({isLogged: this.props.isLogged})
  }
}