访问内部反应构造函数

时间:2017-04-22 12:57:51

标签: javascript reactjs redux

我无法在构造函数中获得使用redux概念实现的道具。

容器组件代码

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获取道具,即物品,但不能在构造函数内部。

用于查看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}
}

最后我的reducer如下所示,

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 个答案:

答案 0 :(得分:4)

您无法在构造函数中访问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状态和组件状态很少是一个好主意,应该尽量避免。它可能导致不一致,并且很难发现错误。

在这种情况下,我发现没有任何理由可以将this.state.itemTitle的所有用法替换为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对象,但通常它代表减速器的整个初始状态,因此使用initialState.item对我来说非常突出。你可能正在为所有的reducers重用一个共享的初始状态对象,所以我不太关心这个。

Object.assign电话是多么令人困惑。我不确定它的目的是在状态中输出替换item的对象,或者是要将action.item附加到数组,还是要将一个数组作为单个项目由此产生的状态。 state = action.item部分对于其在行动中的意图也特别令人费解。

PropTypes UpdateItem要求item成为数组

,这进一步混淆了
UpdateItem.propTypes = {
    item: PropTypes.array.isRequired
};

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

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

从评论更新

Here is a example我在评论中谈论的内容。它是您的代码的简化版本(我没有所有组件。我还修改了一些符合我个人风格的东西,但希望您仍然可以看到它的内容上。