tylersDisplayName
tylersDisplayName

Reputation: 1641

console.log this.state is not showing the current state in react

I'm new to react and toying with a sign-up form. My render method always displays the current state of user.name, user.email and the error attribute is always flagged appropriately.

However, within my bound methods (considerSubmit, validateEmail, etc..) console.log(this.state) outputs my default state, not the current state.

What am I missing here? I thought that .bind(this) would synchronize the state amongst all methods.

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {withStyles, createStyleSheet} from 'material-ui/styles';
import TextField from 'material-ui/TextField';
import Button from 'material-ui/Button';
import Dialog, {
    DialogActions,
    DialogContent,
    DialogContentText,
    DialogTitle,
} from 'material-ui/Dialog';
import Slide from 'material-ui/transitions/Slide';

const popsicle = require('popsicle');
const styleSheet = createStyleSheet('RegistrationProgress', {
    root: {
        maxWidth: 400,
        flexGrow: 1,
    },
});

class RegistrationProgress extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            user: {
                name: null,
                isNameValid: null,
                email: null,
                isEmailValid: null
            },
            notice: {
                title: null,
                message: null,
                open: false,
            }
        };
    }

    handleRequestClose() {
        let noticeState = this.state.notice;
        noticeState.open = false;
        this.setState({notice: noticeState});
    };

    considerSubmit(event) {
        const isSubmitAction = event.key === 'Enter' || event.type === 'click';
        if (isSubmitAction) {
            let userState = this.state.user;
            let formReady = (userState.isNameValid && userState.isEmailValid);
            if (!formReady) {
                this.showNotice("Hold on a sec!", "Make sure your first and last name is provided as well as a proper email address.");
                return;
            }
            var RegistrationProgress = this;
            var element = document.querySelector('meta[name="csrf-token"]');
            var csrf_token = element && element.getAttribute("content");
            console.log(userState, userState.name,this.state.user)
            popsicle.request({
                method: 'POST',
                url: '/register',
                body: {
                    name: userState.name,
                    email: userState.email,
                    _token: csrf_token
                },
                headers: {
                    'X-XSRF-TOKEN': csrf_token
                }
            })
                .use(popsicle.plugins.parse('json'))
                .then(function (res) {
                    console.log(res.status) // => 200
                    console.log(res.body) //=> { ... }
                    console.log(res.get('Content-Type')) //=> 'application/json'
                    RegistrationProgress.showNotice("Yeehaw!", "Account created! Confirm your email to login.");
                })
                .catch(function(error){
                    RegistrationProgress.showNotice("Uh-oh.", "Looks like our server hiccuped when handling your request. Try again.")
                });
        }
        return event;
    }

    showNotice(title = "Whoa!", message) {
        this.setState({
            notice: {
                title: title,
                message: message,
                open: true
            }
        })
    }

    validateName(event) {
        const nameRule = /^(([A-Za-z]+[\-\']?)*([A-Za-z]+)?\s)+([A-Za-z]+[\-\']?)*([A-Za-z]+)?$/;
        let registerName = (event.target.value).trim();
        let userState = this.state.user;
        userState.isNameValid = nameRule.test(registerName);
        console.log(userState)
        this.setState({user: userState})
    }

    validateEmail(event) {
        const emailRule = /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/;
        let registerEmail = (event.target.value).trim();
        let userState = this.state.user;
        userState.isEmailValid = emailRule.test(registerEmail);
        this.setState({
            user: userState
        })
    }

    render() {
        const classes = this.props.classes;
        return (
            <div className="register-form" onKeyPress={this.considerSubmit.bind(this)}>
                <TextField id="name" name="name" label="Full Name" type="text" defaultValue={this.state.user.name}
                           className={classes.input}
                           error={RegistrationProgress.getErrorState(this.state.user.isNameValid)}
                           helperText="" onChange={(event) => this.validateName(event)} marginForm
                />
                <br/>
                <TextField id="email" name="email" label="Email" type="email" defaultValue={this.state.user.email}
                           className={classes.input}
                           error={RegistrationProgress.getErrorState(this.state.user.isEmailValid)}
                           helperText="" onChange={(event) => this.validateEmail(event)} marginForm
                />
                <br />
                <Button raised color="primary" className={'register-button ' + classes.button}
                        onClick={(event) => this.considerSubmit(event)}>
                    Sign Up
                </Button>
                <Dialog open={this.state.notice.open} transition={Slide}
                        onRequestClose={this.handleRequestClose.bind(this)}>
                    <DialogTitle>
                        {this.state.notice.title}
                    </DialogTitle>
                    <DialogContent>
                        <DialogContentText>
                            {this.state.notice.message}
                        </DialogContentText>
                    </DialogContent>
                    <DialogActions>
                        <Button onClick={this.handleRequestClose.bind(this)} color="primary">
                            Got it!
                        </Button>
                    </DialogActions>
                </Dialog>
            </div>
        );
    }

    static getErrorState(value) {
        return (!value && value !== null);
    }
}

RegistrationProgress.propTypes = {
    classes: PropTypes.object.isRequired,
};

export default withStyles(styleSheet)(RegistrationProgress);

Upvotes: 3

Views: 10570

Answers (1)

Finbarr O&#39;B
Finbarr O&#39;B

Reputation: 1464

Your handlers for the components are just binding 'this' to the handler methods but not invoking them.

You can bind 'this' in your constructor, or make your handler functions as 'fat arrow' functions (this is bound automatically then). Then, be sure to set the handlers correctly in your components:

constructor:

constructor(props) {
    super(props);
    this.state = {
        user: {
            name: null,
            isNameValid: null,
            email: null,
            isEmailValid: null
        },
        notice: {
            title: null,
            message: null,
            open: false,
        }
    };
    this.considerSubmit.bind(this);
    this.handleRequestClose.bind(this);
    this.handleRequestClose.bind(this);
}

render:

render() {
    const classes = this.props.classes;
    return (
        <div className="register-form" onKeyPress={this.considerSubmit()}>
            <TextField id="name" name="name" label="Full Name" type="text" defaultValue={this.state.user.name}
                       className={classes.input}
                       error={RegistrationProgress.getErrorState(this.state.user.isNameValid)}
                       helperText="" onChange={(event) => this.validateName(event)} marginForm
            />
            <br/>
            <TextField id="email" name="email" label="Email" type="email" defaultValue={this.state.user.email}
                       className={classes.input}
                       error={RegistrationProgress.getErrorState(this.state.user.isEmailValid)}
                       helperText="" onChange={(event) => this.validateEmail(event)} marginForm
            />
            <br />
            <Button raised color="primary" className={'register-button ' + classes.button}
                    onClick={(event) => this.considerSubmit(event)}>
                Sign Up
            </Button>
            <Dialog open={this.state.notice.open} transition={Slide}
                    onRequestClose={this.handleRequestClose()}>
                <DialogTitle>
                    {this.state.notice.title}
                </DialogTitle>
                <DialogContent>
                    <DialogContentText>
                        {this.state.notice.message}
                    </DialogContentText>
                </DialogContent>
                <DialogActions>
                    <Button onClick={this.handleRequestClose())} color="primary">
                        Got it!
                    </Button>
                </DialogActions>
            </Dialog>
        </div>
    );
}

Upvotes: 0

Related Questions