在react构造函数中访问props

IT技术 javascript reactjs redux
2021-05-01 09:08:49

我无法在使用 redux 概念实现的构造函数中获取props。

容器组件代码

class UpdateItem extends Component{
    constructor(props) {
    super(props);
    console.log(this.props.item.itemTitle) // output: undefined
    this.state = {
        itemTitle: this.props.item.itemTitle,
        errors: {}
    };

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

handleChange(e) {
    //If the input fields were directly within this
    //this component, we could use this.refs.[FIELD].value
    //Instead, we want to save the data for when the form is submitted
    let state = {};
    state[e.target.name] = e.target.value.trim();
    this.setState(state);
}

    handleSubmit(e) {
    //we don't want the form to submit, so we pritem the default behavior
    e.preventDefault();

    let errors = {};
    errors = this._validate();
    if(Object.keys(errors).length != 0) {
        this.setState({
            errors: errors
        });
        return;
    }
    let itemData = new FormData();
    itemData.append('itemTitle',this.state.itemTitle)

    this.props.onSubmit(itemData);
}

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

    componentWillReceiveProps(nextProps){
        if (this.props.item.itemID != nextProps.item.itemID){
            //Necessary to populate form when existing item is loaded directly.
            this.props.getItemByID();
        }
    }


    render(){

        let {item} = this.props;
        return(
            <UpdateItemForm
            itemTitle={this.state.itemTitle}
            errors={this.state.errors}
            />
        );
    }
}

UpdateItem.propTypes = {
    item: PropTypes.array.isRequired
};

function mapStateToProps(state, ownProps){
    let item = {
        itemTitle: ''
    };


    return {
        item: state.itemReducer
    };
}

function mapDispatchToProps (dispatch, ownProps) {
    return {
        getItemByID:()=>dispatch(loadItemByID(ownProps.params.id)),
        onSubmit: (values) => dispatch(updateItem(values))
    }
}

export default connect(mapStateToProps,mapDispatchToProps)(UpdateItem);

在 render() 方法中,可以从 redux 中获取props,即项目,但不能在构造函数中获取。

以及用于查看 redux 实现是否正确的操作代码,

    export function loadItemByID(ID){
        return function(dispatch){
            return itemAPI.getItemByID(ID).then(item => {
                dispatch(loadItemByIDSuccess(item));
            }).catch(error => {
                throw(error);
            });
        };
    }

export function loadItemByIDSuccess(item){
    return {type: types.LOAD_ITEM_BY_ID_SUCCESS, item}
}

最后我的减速机看起来如下,

export default function itemReducer(state = initialState.item, action) {
    switch (action.type) {
        case types.LOAD_ITEM_BY_ID_SUCCESS:
            return Object.assign([], state = action.item, {
                item: action.item
            });
        default:
            return state;
    }
}

我用谷歌搜索没有运气得到答案,我不知道我在哪里犯了错误。如果有人为我指出这将是一个很大的帮助。提前致谢。

1个回答

您无法在构造函数中访问 props 的原因是它只在组件首次安装之前被调用一次。

加载项的操作在componentWillMount函数中调用,该操作发生在调用构造函数之后。

看起来您正在尝试在mapStateToProps函数中设置默认值,但根本没有使用它

function mapStateToProps(state, ownProps){
    // this is never used
    let item = {
        itemTitle: ''
    };


    return {
        item: state.itemReducer
    };
}

我注意到的下一部分是您正在从 redux 获取状态并尝试将其注入组件的本地状态

this.state = {
    itemTitle: this.props.item.itemTitle,
    errors: {}
};

混合 redux state 和 component state 很少是一个好主意,应该尽量避免。它可能导致不一致并且难以发现错误。

在这种情况下,我看不出有任何理由不能替换this.state.itemTitlewith 的所有用法this.props.items.itemTitle并将其从组件状态中完全删除。


观察

你的代码有一些奇怪的地方,让我很难推断出代码背后的意图。

首先是减速机

export default function itemReducer(state = initialState.item, action) {
    switch (action.type) {
        case types.LOAD_ITEM_BY_ID_SUCCESS:
            return Object.assign([], state = action.item, {
                item: action.item
            });
        default:
            return state;
    }
}

您还没有显示initialState对象,但通常它代表减速器的整个初始状态,因此 usinginitialState.item对我来说突出。您可能正在为所有减速器重用共享的初始状态对象,所以我不太关心这一点。

叫什么很混乱Object.assign我不确定它的意图是item在状态中输出一个对象替换,或者它是否要附加action.item到一个数组,或者将一个带有单个项目的数组作为结果状态。state = action.item部分在操作中的意图也特别令人费解。

这进一步混淆了PropTypesfor UpdateItemwhich requires itemto be an array

UpdateItem.propTypes = {
    item: PropTypes.array.isRequired
};

但是组件中的用法将其视为和对象

this.state = {
  // expected some kind of array lookup here |
  //                          V---------------
    itemTitle: this.props.item.itemTitle,
    errors: {}
};

从评论更新

这是我在评论中谈论的一个例子这是您代码的简化版本(我没有您的所有组件。我还修改了一些内容以符合我的个人风格,但希望您仍然可以看到发生了什么。