React Input onSelect Component shows Previous Selection

106 views Asked by At

I've create an autocomplete search input bar using AWS Cloudscape. When I attempt to use the onSelect to save state, it does not save state. When I select a second item from the search bar, the first item then shows up. I assume this is a state async issue. I need the most recent selection, how do I get that?

import React from "react";
import Regions from "./trailforks_regions.json"
import RegionNames from "./region_names.json"
import * as dfd from "danfojs";
import { Autosuggest } from '@cloudscape-design/components';

export class AutoCompleteInputComponent extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            df: new dfd.DataFrame(Regions),
            value: null,
            final_value: "",
            options: [],
            status: "loading",
            regionContext: [],
            uri_value: "",
            loaded: false

        };
    }

    lookupRegionUriName() {
        console.log("Checking for uri region name on:" + this.state.final_value)
        let region_name_split = this.state.final_value.split(",")[0]
        let query_df = this.state.df.query(this.state.df["name"].eq(region_name_split))
        let uri_name = query_df["region_uri_name"].values
        console.log("found:" + uri_name)
        return uri_name
    }

    handleChange = event => {
        this.setState({ value: event.detail.value });
    };

    handleSelect = event => {
        console.log(event) // This shows the correct data! But the set state does not set this data.
        this.setState({ final_value: event.detail.value });
        this.lookupRegionUriName(this.state.final_value)
    };

    handleLoadItems = ({ detail: { filteringText, firstPage, samePage } }) => {
        this.filteringText = filteringText;
        var my_options = RegionNames.filter(regions => regions.toLowerCase().startsWith(this.filteringText.toLowerCase()))
        var region_values = []
        for (var i = 0; i <= my_options.length; i++) {
            region_values.push({ value: my_options[i] })
        }
        this.setState({
            options: region_values.slice(0, 25),
            status: 'loading',
        });
    };


    enteredTextLabel = value => `Use: "${value}"`;

    renderInput() {
        if (this.state.df != null) {
            const { status, value, options, final_value, uri_value } = this.state;
            return (
                <>
                    <Autosuggest
                        onChange={this.handleChange}
                        onSelect={this.handleSelect}
                        onLoadItems={this.handleLoadItems}
                        value={value}
                        options={options}
                        enteredTextLabel={this.enteredTextLabel}
                        ariaLabel="Autosuggest example with suggestions"
                        placeholder="Enter Trailforks Region Name"
                        empty="No matches found"
                        finishedText={this.filteringText ? `End of "${this.filteringText}" results` : 'End of all results'}
                        //status={status}
                        loadingText="searching"
                        filteringType="manual"
                    />
                </>
            )
        } else {
            return (<></>)
        }

    }

    render() {
        return (
            <>
                {this.renderInput()}
            </>
        )
    }
}

Dom Example

1

There are 1 answers

0
Joshua Faust On

Figured it out. It was a state issue, here are the changes for future people:

import React from "react";
import Regions from "./regions.json"
import RegionNames from "./region_names.json"
import * as dfd from "danfojs";
import { Autosuggest } from '@cloudscape-design/components';

export class AutoCompleteInputComponent extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            df: new dfd.DataFrame(Regions),
            value: null,
            final_value: "",
            options: [],
            status: "loading",
            regionContext: [],
            uri_value: "",
            loaded: false

        };
    }

    updateRegion(state_object) {
        this.lookupRegionUriName()
        return state_object.final_value
    }

    lookupRegionUriName() {
        console.log("Checking for uri region name on:" + this.state.final_value)
        let region_name_split = this.state.final_value.split(",")[0]
        let query_df = this.state.df.query(this.state.df["name"].eq(region_name_split))
        let uri_name = query_df["region_uri_name"].values
        this.setState({uri_value: uri_name})
        console.log("found:" + uri_name)
    }

    handleChange = event => {
        this.setState({ value: event.detail.value });
    };

    handleSelect = event => {
        console.log(event) // This shows the correct data! But the set state does not set this data.
        this.setState({ final_value: event.detail.value });
        this.lookupRegionUriName(this.state.final_value)
    };

    handleLoadItems = ({ detail: { filteringText, firstPage, samePage } }) => {
        this.filteringText = filteringText;
        var my_options = RegionNames.filter(regions => regions.toLowerCase().startsWith(this.filteringText.toLowerCase()))
        var region_values = []
        for (var i = 0; i <= my_options.length; i++) {
            region_values.push({ value: my_options[i] })
        }
        this.setState({
            options: region_values.slice(0, 25),
            status: 'loading',
        });
    };


    enteredTextLabel = value => `Use: "${value}"`;

    renderInput() {
        if (this.state.df != null) {
            const { status, value, options, final_value, uri_value } = this.state;
            return (
                <>
                    <Autosuggest
                        onChange={this.handleChange}
                        onSelect={event => {this.setState({final_value: event.detail.value}, () => {this.updateRegion(this.state)})}}
                        //onSelect={this.handleSelect}
                        onLoadItems={this.handleLoadItems}
                        value={value}
                        options={options}
                        enteredTextLabel={this.enteredTextLabel}
                        ariaLabel="Autosuggest example with suggestions"
                        placeholder="Enter Trailforks Region Name"
                        empty="No matches found"
                        finishedText={this.filteringText ? `End of "${this.filteringText}" results` : 'End of all results'}
                        status={status}
                        loadingText="searching"
                        filteringType="manual"
                    />
                </>
            )
        } else {
            return (<></>)
        }

    }

    render() {
        return (
            <>
                {this.renderInput()}
            </>
        )
    }
}