简体   繁体   English

如何访问设置 redux props 以响应状态?

[英]How to access to set redux props to react state?

This is my code and I try to set email of user to state and set it with other data:这是我的代码,我尝试将用户的电子邮件设置为声明并使用其他数据进行设置:

  import React, {Component} from "react";
import PropTypes from "prop-types";
import * as actionCreators from '../../actions/authAction';

import {loadUser, setPass , register} from "../../actions/authAction";
import {connect} from "react-redux";
import { bindActionCreators } from "redux";
import {clearError} from "../../actions/errorAction";
import {toast} from "react-toastify";
import store from "../../store";


class RegisterFinal extends Component {

    componentDidMount() {
        store.dispatch(loadUser());

    }
    componentDidUpdate(nextProps) {
        if (nextProps.user !== this.props.user) {
            this.setState({ email: this.props.user});
        }
    }

    state = {
        userName: "",
        password: "",
        passwordConfirm: "",
        email: "",
        msg: null
    }

    static propTypes = {
        isAuthenticated: PropTypes.bool,
        setPass: PropTypes.bool,
        register: PropTypes.func.isRequired,
        auth: PropTypes.object.isRequired,
        user : PropTypes.object.isRequired,
    };

    onSubmit = (e) => {
        e.preventDefault();
        const {password, userName, email} = this.state
        const setPass = {
            password, userName, email
        }
        this.props.setPass(setPass);
        const {passwordConfirm} = e.target;
        const errors = {};
        if (password.value !== passwordConfirm.value) {
            errors.passwordMismatch = "Entered passwords do not match.";
            console.log(errors)
        }
    }
    onChange = (e) => {
        this.setState({
            [e.target.name]: e.target.value,
        });
    };

    render() {
        return (
            <div className={"container"}>
                <div className={"row row-of-final-register justify-content-center"}>
                    <div className={"mt-5 register-teacher-inputs-box final-register-teacher-inputs-box"}>
                        <div className={"final-register-wrapper"}>
                          
                        <form className={"mt-5"} onSubmit={this.onSubmit}>
                            <div className={"row"}>
                                <div className={"col-12"}>
                                    <label
                                        htmlFor={"userName"} className={"text-right username-label"}>
                                        <span>*</span>
                                    </label>
                                    <input type="text" className="form-control w-100" placeholder={"Username"}
                                           name={"userName"}
                                           autoComplete="true"
                                           value={this.userName}
                                           onChange={this.onChange}
                                           onFocus={(e) => e.target.placeholder = ""}
                                    />
                                </div>
                            </div>
                            <div className={"row"}>
                                <div className={"col-12 col-lg-6 mt-3"}>
                                    <label
                                        htmlFor={"password"} className={" text-right"}>
                                        <span>*</span>
                                    </label>
                                    <input type="password" className="form-control " placeholder={"Password"}
                                           name={"password"}
                                           value={this.password}
                                           onChange={this.onChange}
                                  
                                           onFocus={(e) => e.target.placeholder = ""}
                                    />
                                </div>
                
                            </div>
                            <div className={"row mt-3 pt-2"}>
                                <div className={"col-12 final-register-wrapper final-register-btn"}>
                                    <button type={"submit"} className={"final-register-btn"}>Submit</button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        )
    }
}


function mapStateToProps (state , ownProperties)  {
    console.log(state.auth.user)
    return {
        setPass: state.auth.setPass,
        isAuthenticated: state.auth.isAuthenticated,
        error: state.error,
        auth: state.auth,
        user : state.auth.user,



    }

};
function mapDispatchToProps(dispatch) {
    return bindActionCreators(actionCreators, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps

)(RegisterFinal);

When run I have this data in my email state :运行时,我的电子邮件状态中有这些数据: 显示用户的所有数据

But when I try to access email get Error that cannot read property 'email' of undefined, I just change email : this.props.user to email : this.props.user.email in componentDidUpdate.但是当我尝试访问 email get Error that cannot read property 'email' of undefined 时,我只是在 componentDidUpdate email : this.props.user email : this.props.user.email更改为email : this.props.user.email I actually need to set redux props to react state.我实际上需要设置 redux props 来响应状态。 I'm new in redux.我是 redux 的新手。 Here share my project : my project在这里分享我的项目: 我的项目

Here is a working example that will async load a user, set the initial value of a textbox with it's value and submit changes:这是一个工作示例,它将异步加载用户,使用它的值设置文本框的初始值并提交更改:

 const { Provider, connect } = ReactRedux; const { createStore, applyMiddleware, compose } = Redux; const { createSelector } = Reselect; const initialState = { user: null, loading: true, //initially set loading to true }; //helper for async const later = (value) => new Promise((resolve) => setTimeout(() => resolve(value), 2000) ); //action types const CHANGE_USER = 'CHANGE_USER'; const CHANGED_USER = 'CHANGED_USER'; const LOAD_USER = 'LOAD_USER'; const LOADED_USER = 'LOADED_USER'; //action creators const loadUser = () => ({ type: LOAD_USER, }); const loadedUser = (user) => ({ type: LOADED_USER, payload: user, }); const changeUser = () => ({ type: CHANGE_USER, }); const changedUser = (user) => ({ type: CHANGED_USER, payload: user, }); // action thunks const loadUserThunk = () => (dispatch) => { dispatch(loadUser()); return later({ email: 'original-email', }).then((user) => dispatch(loadedUser(user))); }; const changeUserThunk = (email) => (dispatch) => { dispatch(changeUser()); return later({ email, }).then((user) => dispatch(changedUser(user))); }; const reducer = (state, { type, payload }) => { if (type === LOAD_USER || type === CHANGE_USER) { return { ...state, loading: true }; } if (type === LOADED_USER || type === CHANGED_USER) { return { ...state, user: payload, loading: false, }; } return state; }; //selectors const selectUser = (state) => state.user; const selectLoading = (state) => state.loading; const selectUserEmail = createSelector( [selectUser], //want to use user?.email but SO babel is too old (user) => user && user.email ); //creating store with redux dev tools const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( reducer, initialState, composeEnhancers( applyMiddleware( ({ getState, dispatch }) => (next) => ( action //simple thunk implementation ) => typeof action === 'function' ? action(dispatch, getState) : next(action) ) ) ); class App extends React.PureComponent { state = { email: '', initial: true, //only initially set from redux }; componentDidUpdate() { if (!this.props.loading && this.state.initial) { this.setState({ email: this.props.email, initial: false, }); } } //arrow function so you don't need to bind for "this" context onSubmit = (e) => { e.preventDefault(); this.props.dispatch(changeUserThunk(this.state.email)); //reset initial this.setState({ initial: true }); }; emailChanged = (e) => this.setState({ email: e.target.value }); componentDidMount() { this.props.dispatch(loadUserThunk()); } render() { return ( <form onSubmit={this.onSubmit}> <input type="text" onChange={this.emailChanged} value={this.state.email} // do not edit when loading disabled={this.props.loading} /> <input type="submit" /> {this.props.loading && 'loading...'} </form> ); } } //do not use store in your components, connect will provide // dispatch on this.props when mapDispatchToProps is // undefined or you can pass an object as mapDispatchToProps const ConnectedApp = connect((state) => ({ email: selectUserEmail(state), //select state.user.email as props.email loading: selectLoading(state), }))(App); ReactDOM.render( <Provider store={store}> <ConnectedApp /> </Provider>, document.getElementById('root') );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script> <div id="root"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM