简体   繁体   中英

Intermittent React Uncaught Error: Objects are not valid as a React child

I have a Header component which renders some links, depending on whether a user is signed in or not.

This component loads fine, displays signin and signup links fine. Clicking on those links takes me to those components, which function as they should. Once I sign in, the header changes to display a signout link.

However, when I sign out, things go wrong. The signin and signup links display fine, but they are no longer functional. Clicking on the signup link gives the following error:

Uncaught Error: Objects are not valid as a React child (found: object with keys {}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of Signin .

Clicking on the link again produces this:

bundle.js:4297 Uncaught TypeError: Cannot read property 'getHostNode' of null

I've read similar questions on here, and typically they involved someone trying to render an object as opposed to one of its properties. However, this isn't the case here-or am I missing something?

My code:

Header:

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

class Header extends Component{
    renderLinks(){
        if(this.props.authenticated){
            return <li className="nav-item ">
                <Link className="nav-link" to="/signout">Sign Out</Link>
            </li>
        }else{
            return [<li className="nav-item page-scroll" key={1}>
                        <Link className="nav-link page-scroll" to="/signin">Sign In</Link>
                    </li>,
                    <li className="nav-item" key={2}>
                        <Link className="nav-link page-scroll" to="/signup">Sign Up</Link>
                    </li>
           ]
        }
    }

    render() {
        return (
            <div className="container-fluid header">
                <nav className="navbar navbar-toggleable-md navbar-inverse bg-inverse">
                    <div className="navbar-nav">
                            <Link to="/" className="navbar-brand">
                                    <img alt="Trellis" src="../../images/trellis.png" />
                            </Link>
                            <ul className="nav navbar-nav">
                                {this.renderLinks()}
                            </ul>
                        </div>

                </nav>
            </div>
        );
    }
}

function mapStateToProps(state){
    return{
        authenticated: state.auth.authenticated
    };
}
export default connect(mapStateToProps)(Header);

Signin component:

import React, { Component } from 'react';
import { reduxForm, Field } from 'redux-form';
import * as actions from '../../actions';
import { connect } from 'react-redux'; 
import { Link } from 'react-router';

class Signin extends Component {

    handleFormSubmit({ email, password }) {
        this.props.signInUser({email, password});
    }

    renderInput(field) {
        if(!field.className) { field.className = "form-control" }
        if(!field.type) { field.type = "text" }

        return (
            <div>
                <Field name={field.name} id={field.name} type={field.type} className={field.className} component="input" />
            </div>
        )
    }
    renderAlert(){
        if(this.props.errorMessage){
            return(
                    <div className="alert alert-danger">
                        <strong>Oops!</strong> {this.props.errorMessage}
                    </div>
                );
    }
}

    render() {
        const { handleSubmit } = this.props

        return (
            <form className="sign-in" onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
                <fieldset className="form-group">
                    <label>Email:</label>
                    {this.renderInput({ name: "email", type: "email" })}
                </fieldset>
                <fieldset className="form-group">
                    <label>Password:</label>
                    {this.renderInput({ name: "password", type: "password" })}
                </fieldset>
                <div className="password-forgot">
                    <Link to="/reset-password">I forgot my password</Link>
                </div>
                {this.renderAlert()}
                <button action="submit" className="btn btn-primary">Sign in</button>
            </form>
        )
    }
}

function mapStateToProps(state){
    return{errorMessage: state.auth.error};
 }

Signin = connect(mapStateToProps, actions)(Signin)

export default reduxForm({
  form: 'signin'
})(Signin)

Signout component:

import React, {Component} from 'react';
import {connect} from 'react-redux';
import * as actions from '../../actions';

class Signout extends Component {
    componentWillMount() {
        this.props.signOutUser();
    }
    render() {
        return <div>Sorry to see you go!</div>;
    }
}

export default connect(null, actions)(Signout);

Signin action:

export function signInUser(props) {
    const { email, password } = props;
    return function(dispatch){
        axios.post(`${ROOT_URL}/signin`, {email, password})
            .then(response => {
                localStorage.setItem('user', JSON.stringify(response.data));
                dispatch({ type: AUTH_USER });
                browserHistory.push('/dashboard');
        })
            .catch((err) => {
                console.log(JSON.stringify('login error:', err));
                dispatch(authError(SIGNIN_FAILURE, 'Bad login credentials'));
        });
    };
}

Signout action:

export function signOutUser() {
    localStorage.clear();
    return { type: UNAUTH_USER };
}

(As per the comments on the original post)

The issue was in the SignIn render component you call the renderAlert() function which returns this.props.errorMessage as part of the JSX element. This was the only part of the JSX rendered by SignIn which could've been as issue (as per your code).

Turns out this.props.errorMessage was actually an object not a string as you had thought, hence the error regarding an object as a React child.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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