组件视图未更新,但redux存储正在更新

时间:2019-11-14 06:04:01

标签: reactjs redux

问题是下拉式组件在首次加载时在组件视图上未显示任何选项,但在重新加载后显示。我从商店获取商店数据作为响应,但组件未获取数据我在下面放置了控制台日志,我从mapStateToProps的控制台日志中获取数据,但是我在componentDidMount的控制台日志中发现了一个空数组,上面写着this.props.skills.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

下面是组件:

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动作

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))
    }
}

3 个答案:

答案 0 :(得分:0)

正在componentDidMount中触发分派动作,此触发后,您的代码将移至下一行。

目前,当您打印console.log('The skill options are .......', this.props.skills)时,API调用仍在进行,因此商店更新尚未发生。出于相同的原因,技能变量为[]

现在,一旦您的API完成,它将更新您的redux存储。您拥有的组件应该能够在componentDidUpdate函数中接收更新的数据。

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

现在,由于这里有数据,您可以通过此功能更新状态。

除此答案外,仅提供少量反馈,可帮助您遵循良好做法。 您最好不要将值从商店复制到您的州。它使您的代码确实令人迷惑并且难以调试。

有关更多详细信息,请阅读here

通过您的代码,将技能完全转移到redux存储并创建无状态组件可以轻松实现相同目的。

答案 1 :(得分:0)

componentDidMount仅在第一次调用时,然后您将分派动作以获取技能,因此它将作为道具传递给组件。因此,您应该使用的生命周期方法是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

答案 2 :(得分:0)

啊哈。我明白了您显然会在componentDidmount中得到一个空数组。您将必须在componentWillrecieveProps中编写以下代码。调用动作后,将需要一些时间来通过reducer更新状态。因此,紧接动作调用后的行将不会使用适当的道具进行更新。

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 })