Search code examples
reactjssharepointspfxfluentui-react

Dropdown clearing but state remains after component update


I've been following a few tutorials on creating a SPFX webpart form using fluent ui and React.

My webpart component is constructed as follows:

 constructor(props: IOrderingProps, wpState: ICurrentWpState) {
    super(props);
    // init the state properties
    this.state = {
      companyDropDownSelected: "",
      cart: null
    };

    this.showStateClicked = this.showStateClicked.bind(this);
    this.onCompanyChange = this.onCompanyChange.bind(this); 
}

My render:

    public render(): React.ReactElement<IOrderingProps> {
    return (

      <div className={styles.tpOrdering}>
        <div className={styles.container}>

          <Stack tokens={stackTokens}>
            <span className={styles.title}>{this.props.description}</span>
            <Dropdown
              placeholder="Select a company"
              label="Company"
              selectedKey={this.state.companyDropDownSelected}
              id="companyDdl"
              styles={dropdownStyles}
              options={this.props.companyOptions}
              onChange={this.onCompanyChange}
            />
            <PrimaryButton text="Show Comp state" onClick={this.showStateClicked} />                        
            <table id="example" className="display partsTable">
            </table>
          </Stack>

        </div>
      </div>
    );
  }

Note my selected key is stored in state. My onChange event for the dropdown:

public onCompanyChange = async (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): Promise<void> => {    
    const selectedKey: string = item ? (item.key as string) : "";
    this.setState({ companyDropDownSelected: selectedKey });
    this.fetchParts();
  }

This all works fine. However, if I update any value in the WebPart property pane, I want the dropdown to retain it's selected value. Currently it triggers a componentDidUpdate and clears the dropdown even though the the state remains. How do I reset the dropdown to it's existing selected key state?

My componentDidUpdate implementation:

public componentDidUpdate(prevProps: IOrderingProps, prevState: ICurrentWpState, prevContext: any): void {
    // re-execute if limit has changed.
    if (this.props.limit !== prevProps.limit) {
      this.fetchParts();      
    }
  }

Even if I do nothing in componentDidUpdate it clears the dropdown, even thought the state for selected key still exists.


Solution

  • This ended up being an async/await problem and not a state or control issue. The problem was the companyOptions stored in the properties is being passed into the component from the webpart. They are being created via an async call to an API.

    const element: React.ReactElement<IOrderingProps> = React.createElement(
      Ordering,
      {
        description: this.properties.description,
        context: this.context,
        limit: this.properties.limit,
        msalInstance: this.msalConfig,
        companyOptions: await this.getCompanyOptions()
        
      }
    );
    

    The fetch and token calls inside this.getCompanyOptions() weren't properly awaited. Thus, the dropdown selected key was trying to be reset on componentUpdate when companyOptions was still null.

    <Dropdown
        placeholder="Select a company"
            label="Company"
            selectedKey={this.state.companyDropDownSelected}
            id="companyDdl"
            styles={dropdownStyles}
            options={this.props.companyOptions}
            onChange={this.onCompanyChange}
            />
    

    This is working as expected now that there are valid options when the component updates.