简体   繁体   中英

The Component view does not get updated but the redux store is getting updated

The issue is the dropdown components are not showing any options on the component view when loaded for the first time but shows up after reloading.I am getting the store data as a response from the store but the component is not getting the data.I have put console logs below, I am getting data from the console log of mapStateToProps,but I found empty array from the console log inside componentDidMount stating this.props.skills.Is there any issue with the code in reducer or the component?

Below is the reducer:

Skill Reducer:

const skillInitialState = {
    skillList: []
}
const skillReducer = (state = skillInitialState, action) => {

    switch (action.type) {
        case 'GET_SKILLS':
            console.log('the reducer state is ......$$$$$$$$$$$$ ', state)
            console.log('the skillsssss.....%%%%%%****', action.payload)
            return {
                ...state,
                skillList: action.payload
            }

        default:
            return state
    }

}
export default skillReducer

Below is the component:

import React from 'react';
import Select from 'react-select';
import { connect } from 'react-redux';
import { startGetSkills, startGetEmployeeSkills } from "../../action/index.js";

class MultiSelect extends React.Component {
    constructor() {
        super()
        this.state = {
            options: [],
            selectedOptions: [],
        }
    }

    componentDidMount() {
        const skillOptions = []
        this.props.startGetSkills()
        this.props.startGetEmployeeSkills()

        console.log('The skill options are .......', this.props.skills)
        this.props.skills.forEach((skill) => {
            console.log('The skills are ......', skill)
            skillOptions.push({
                value: skill._id,
                label: skill.skillName.charAt(0).toUpperCase() + skill.skillName.slice(1),
                _id: skill._id
            })
        })
        this.setState({ options: skillOptions })
        this.setState({ selectedOptions: this.props.selectSkill })
    }

    render() {
        const { skills, heading, index } = this.props
        const { options } = this.state
        return (
            <div>
                <label> {heading} </label>
                <Select
                    isMulti={true}
                    defaultValue={this.props.selectSkill}
                    value={this.state.selectedOptions}
                    options={options}
                    onChange={(e) => {
                        this.setState({ selectedOptions: e })
                        this.props.handleSkillChange(e)
                    }}
                />
            </div>
        );
    }
}

const mapDispatchToProps = dispatch => {
    return {
        startGetSkills: () => {
            dispatch(startGetSkills())
        },
        startGetEmployeeSkills: () => {
            dispatch(startGetEmployeeSkills())
        }
    }
}
const mapStateToProps = (state) => {
console.log('the skills mapstateToprops are.......',state.skill.skillList)
    return {
        skills: state.skill.skillList,
        employees: state.employee,
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MultiSelect)

UserSkills actions

import axios from '../../src/config/axios';
import { GET_SKILLS } from './types';

export const getSkills = (skills) => {
    return {
        type: GET_SKILLS,
        payload: skills
    }
}

export const startGetSkills = () => {
    return (dispatch) => {
        axios.get(`/users/skills`, {
            headers: {
                'x-auth': localStorage.getItem('token')
            }
        })
            .then((response) => {
                console.log('the skills... response is .....', response.data)
                dispatch(getSkills(response.data))
            })
            .catch(err => console.log(err))
    }
}

The dispatch action is being fired in componentDidMount and after this fire your code moves on to the next line.

At this point in time, when you print console.log('The skill options are.......', this.props.skills) your API call is still taking place so your store update has not happened. For the same reason, the skills variable is [] .

Now once your API completes, it updates your redux store. The component which you have should be able to receive the updated data in the componentDidUpdate function.

 componentDidUpdate(prevProps) {
    console.log(this.props); // updated skills should be available
  }

Now, since you have the data here you can update the state from this function.

Apart from this answer just small feedback to help you follow good practices. You should not ideally copy the values from the store to your state . It makes your code really confusing and hard to debug.

Please read here for more details.

From your code, the same can be easily achieved by moving the skills completely to redux store and create stateless components.

componentDidMount will only be invoked the first time, then you are dispatching action to fetch the skills, so it would then be passed as props to the component. So the life cycle method you should be using is componentDidUpdate

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.skills !== prevProps.skills) {
    // update the state here with updated data
  }
}

componentDidUpdate doc

Aha. I get it now. You will get obviously an empty array in componentDidmount. You will have to write the following code in componentWillrecieveProps. After calling an action,it will take some time to get the state updated through reducers. So,the lines immediately following action call won't get updated with proper props.

this.props.skills.forEach((skill) => {
        console.log('The skills are ......', skill)
        skillOptions.push({
            value: skill._id,
            label: skill.skillName.charAt(0).toUpperCase() + skill.skillName.slice(1),
            _id: skill._id
        })
    })
    this.setState({ options: skillOptions })
    this.setState({ selectedOptions: this.props.selectSkill })

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