Irmantas Želionis
Irmantas Želionis

Reputation: 2324

State can't access props

I am trying to add selectedUserIds in state constructor by using userListIds from props. However, it seems that at the time when constructor is executed the value in props is not set yet thus I am getting null.

However, when I am printing this.props.userListIds at the beginning of the render it shows just fine. Problem is somewhere else. What might be the solution? Here is the code:

 const mapStateToProps = (state: State, props: OwnProps): PropsFromState => ({
      userList: getCompanyTeamListSelector(state),
      userListIds: state.ddls.companyUsers.map(element => Number(element.id))
    });


@connect(mapStateToProps)
export default class EmailModal extends React.Component<OwnProps & Partial<PropsFromDispatch> & Partial<PropsFromState>, OwnState> {
  constructor(props: OwnProps) {
    super(props);
    this.state = {
      valueSelected: true, selectedUserIds: this.props.userListIds // HERE
    }}

Upvotes: 0

Views: 288

Answers (2)

blaz
blaz

Reputation: 4068

Props is external data resource for a React component, so you should always assume that props data is not reliable, and take care of empty/undefined props in your component.

Given constructor function is executed before the first rendering in component lifecycle, it's possible that during the execution of constructor function, props.userListIds can be empty, and at render, it's retrieved and ready to be used. If you really want to store userListIds in local state, you can use getDerivedStateFromProps to update local state:

public static getDerivedStateFromProps(nextProps: IProps, prevState: IState) {
  return (nextProps.userListIds != prevState.selectedUserIds) ? 
    { selectedUserIds: nextProps.userListIds } :
    null
}

But same as other comments here, I am also against the idea of copying props to local state, since you will have 2 separated sources of truth for same piece of data and need to update local state whenever your props changes. You can consider directly using props.userListIds instead.

Upvotes: 1

Nino Filiu
Nino Filiu

Reputation: 18493

You're doing React wrong. If the value can be accessed in the props, the value should stay in the props. Duplicating the data between the props and the state can lead to useless component re-rendering, and most importantly many bugs, especially when plugging libraries like React-Redux that will extensively manipulate the props.

Oh, and use props in the constructor, not this.props.

Upvotes: 1

Related Questions