Home > Mobile >  React select is not updating for default value
React select is not updating for default value

Time:06-09

I have a view that can be called both for creating new entry and updating an existing one.

When Im creating a brend new post, eveything works as expected. When editing an existing post, the select box for regions is filled AND the current region is selected. However, for the cities, the select box contains all the cities that belong to the region. But at the same time, the current city is not selected.
Both in the console and in the html-span I can see that the id is correct. But inside the option nothing happens.

EDIT

Full code that works for testing.

In package.json:

...
"react": "18.0.0",
"react-dom": "18.0.0",
"react-router-dom": "6.3.0",
"react-scripts": "4.0.0"

In App.js:

<Route path="test" element={<Test />} />

In Test.js

import React, {useState, useEffect} from "react";

export const Test = () => {
    const [name, setName] = useState('');
    const [city, setCity] = useState('');
    const [region, setRegion] = useState('');
    const [regions, setRegions] = useState([]);
    const [cities, setCities] = useState([]);
    const [fetchingCities, setFetchingCities] = useState(false);

    const getCities = async () => {
        return [
            {_id: 1, region: 'region1', cities: [{id: '6293609d86af877f09bb9bc1', name: 'city1'},{id: '6293609d86af877f09bb9bc2', name: 'city2'}]}
            ,{_id: 2, region: 'region2', cities: [{id: '6293609d86af877f09bb9bc3', name: 'city3'},{id: '6293609d86af877f09bb9bc4', name: 'city4'}]}
        ]
    }

    const getAllCities = async () => {
        const all = await getCities();
        setRegions(all);
        const form = {
            region: 1,
            city: '6293609d86af877f09bb9bc1',
            name: 'testname'
        };
        if(form){
            setName(form.name);
            const cts = all.filter(e => e._id === Number(form.region));
            if(cts && cts.length && cts[0].cities){
                setCities(cts[0].cities);
                setRegion(form.region);
                setCity(form.city);
                console.log('form.city',form.city);
            }
        }

    }


    const citySelected = (value) => {
        console.log("value",value);
        setCity(value);
    }

    const cityChanged = (value) => {
        console.log("cityChanged",value);
        const cts = regions.filter(e => e._id === Number(value));
        console.log("cts",cts);
        if(cts && cts.length && cts[0].cities){
            setCities(cts[0].cities);
            setRegion(value);
        }
    }

    useEffect(() => {
        if(!fetchingCities){
            setFetchingCities(true);
            getAllCities();
        }
    }, []);

    return (
        <>
            <div>
                <div>
                    <input type="text" defaultValue={name} onChange={e => setName(e.target.value)}/>
                </div>
                <div>
                    {
                        regions && regions.length > 0 &&
                        <select defaultValue={region} onChange={e => cityChanged(e.target.value)}>
                            <option value="">
                                Select
                            </option>
                            {regions.map((region, index) => (
                                <option key={index} value={region._id}>
                                    {region.region}
                                </option>
                            ))}
                        </select>
                    }
                </div>
                <div>
                    <select defaultValue={city} onChange={e => citySelected(e.target.value)}>
                        <option value="">
                            Select
                        </option>
                        {cities && cities.length > 0 && cities.map((city, index) => (
                            <option key={index} value={city.id}>
                                {city.name}
                            </option>
                        ))}
                    </select>
                </div>


                <span>city:{city}</span>
            </div>
        </>
    );
};  

CodePudding user response:

You can add a useEffect which sets the value of city every time cities changes.

useEffect(() => {
  setCity(cities[0]?.id)
  //setCity(undefined) or this if you don't want a city to be preselected. 
}, [cities])

You can also add a selected option to verify make sure the selected city is the one shown in the dropdown.

{cities && cities.length > 0 && (
  cities.map((cityOption: any, index: any) => (
    <option
      selected={cityOption.id === city}
      key={index}
      value={cityOption.id}
    >
      {cityOption.name}
    </option>
  ))
)}

CodePudding user response:

Turns out the solution is to add the "value" attribute:

<select onChange={e => citySelected(e.target.value)} value={city}>
  • Related