2

My component receives profile and errors from the parent. Within the component static getDerivedStateFromProps sets the new state should the component receive new data from the parent.

...
constructor(props) {
        super(props);

        this.state = {
            displaySocialInputs: false,
            handle: '',
            company: '',
            website: '',
            location: '',
            status: '',
            skills: '',
            githubusername: '',
            bio: '',
            twitter: '',
            facebook: '',
            linkedin: '',
            youtube: '',
            instagram: '',
            errors: {}
        };

        this.onChange = this.onChange.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
    }
...

static getDerivedStateFromProps(nextProps) {
        if (nextProps.errors) {
            console.log('nextProps.errors:', nextProps.errors);
            return { errors: nextProps.errors };
        }

        if (nextProps.profile.profile) {
            const profile = nextProps.profile.profile;

            // bring skills array back to csv
            const skillsCsv = profile.skills.join(',');

            // if a profile field wasn't provided set it to an empty string
            profile.company = !isEmpty(profile.company) ? profile.company : '';
            profile.website = !isEmpty(profile.website) ? profile.website : '';
            profile.location = !isEmpty(profile.location) ? profile.location : '';
            profile.githubusername = !isEmpty(profile.githubusername) ? profile.githubusername : '';
            profile.bio = !isEmpty(profile.bio) ? profile.bio : '';
            profile.social = !isEmpty(profile.social) ? profile.social : {};
            profile.twitter = !isEmpty(profile.social.twitter) ? profile.social.twitter : '';
            profile.facebook = !isEmpty(profile.social.facebook) ? profile.social.facebook : '';
            profile.linkedin = !isEmpty(profile.social.linkedin) ? profile.social.linkedin : '';
            profile.youtube = !isEmpty(profile.social.youtube) ? profile.social.youtube : '';
            profile.instagram = !isEmpty(profile.social.instagram) ? profile.social.instagram : '';

            // set component state
            return {
                handle: profile.handle,
                company: profile.company,
                website: profile.website,
                location: profile.location,
                status: profile.status,
                skills: skillsCsv,
                githubusername: profile.githubusername,
                bio: profile.bio,
                twitter: profile.twitter,
                facebook: profile.facebook,
                linkedin: profile.linkedin,
                youtube: profile.youtube,
                instagram: profile.instagram
            };
        }

        return null;
    }

The code above prevents the profile object from displaying on the page. When the

if (nextProps.errors) {
            console.log('nextProps.errors:', nextProps.errors);
            return { errors: nextProps.errors };
        }

part is commented out the profile data displays Ok but the errors data cannot display.

How do I get both errors and profile object to display? On my component submit the component field data submits to the parent so if all the required fields are not empty there should be no errors coming in.

The complete repo is on https://github.com/ElAnonimo/DevConnector/blob/master/client/src/components/common/ProfileForm.js

UPDATE 1

The parent component EditProfile.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import PropTypes from 'prop-types';
import ProfileForm from '../common/ProfileForm';
import { createProfile, getCurrentProfile } from '../../actions/profileActions';

class EditProfile extends Component {
    constructor(props) {
        super(props);

        this.onSubmit = this.onSubmit.bind(this);
    }

    componentDidMount() {
        this.props.getCurrentProfile();
    }

    onSubmit(profileData) {
        this.props.createProfile(profileData, this.props.history);
    }

    render() {
        return <ProfileForm profile={this.props.profile} errors={this.props.errors} onSubmit={this.onSubmit} />
    }
}

EditProfile.propTypes = {
    profile: PropTypes.object.isRequired,
    errors: PropTypes.object.isRequired,
    createProfile: PropTypes.func.isRequired,
    getCurrentProfile: PropTypes.func.isRequired
};

const mapStateToProps = (state) => ({
    profile: state.profile,
    errors: state.errors
});

export default connect(mapStateToProps, { createProfile, getCurrentProfile })(withRouter(EditProfile));
El Anonimo
  • 1,759
  • 3
  • 24
  • 38

1 Answers1

2

To return both the data, create an object first then add the key-values in respective if conditions and finally return that object. By that way it will execute both if conditions.

Like this:

static getDerivedStateFromProps(nextProps) {

    let obj = {};

    if (nextProps.errors) {
        obj.errors = nextProps.errors;
    }

    if (nextProps.profile.profile) {
        const profile = nextProps.profile.profile;

        // bring skills array back to csv
        const skillsCsv = profile.skills.join(',');

        // if a profile field wasn't provided set it to an empty string
        profile.company = !isEmpty(profile.company) ? profile.company : '';
        profile.website = !isEmpty(profile.website) ? profile.website : '';
        profile.location = !isEmpty(profile.location) ? profile.location : '';
        profile.githubusername = !isEmpty(profile.githubusername) ? profile.githubusername : '';
        profile.bio = !isEmpty(profile.bio) ? profile.bio : '';
        profile.social = !isEmpty(profile.social) ? profile.social : {};
        profile.twitter = !isEmpty(profile.social.twitter) ? profile.social.twitter : '';
        profile.facebook = !isEmpty(profile.social.facebook) ? profile.social.facebook : '';
        profile.linkedin = !isEmpty(profile.social.linkedin) ? profile.social.linkedin : '';
        profile.youtube = !isEmpty(profile.social.youtube) ? profile.social.youtube : '';
        profile.instagram = !isEmpty(profile.social.instagram) ? profile.social.instagram : '';

        // set component state
        const temp = {
            handle: profile.handle,
            company: profile.company,
            website: profile.website,
            location: profile.location,
            status: profile.status,
            skills: skillsCsv,
            githubusername: profile.githubusername,
            bio: profile.bio,
            twitter: profile.twitter,
            facebook: profile.facebook,
            linkedin: profile.linkedin,
            youtube: profile.youtube,
            instagram: profile.instagram
        };

        obj = { ...obj, ...temp };
    }

    return obj;
}
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • There is no `obj` property on the component state. All the individual fields are set to the state. Please see the edit. – El Anonimo Feb 20 '19 at 07:20
  • obj is an object that will be merged with state object, `const obj={}; return obj;` and `return {};` is same, just different ways of writing :) – Mayank Shukla Feb 20 '19 at 07:22
  • ultimately we need to return an object with key-value pairs, keys we want to update in state. try that code let me know if you face any issue. – Mayank Shukla Feb 20 '19 at 07:25
  • It seems to work Ok. Another thing: how do I get rid of the `errors` object when visiting another p[age then returning to the component page? The field error still displays. – El Anonimo Feb 20 '19 at 07:35
  • 1
    add one more condition as `else if (!nextProps.errors) { obj.errors = ''; }` it will remove the errors, if errors is an object then assign the empty object :) – Mayank Shukla Feb 20 '19 at 07:52
  • Here it's more complicated. The `errors` object (not a String) comes from the parent so the parent will still send it to the child `ProfileForm` component. – El Anonimo Feb 20 '19 at 08:21