1

I'm trying to set a default value to autocomplete, the value of which is getting fetched from the URL in useEffect hook, but I'm unable to do so.

I'm fetching some data from a URL and then setting it to selectedMode & the variable selectedMode is used in setting default value in autocomplete field, but if I'm setting some default value in the selected mode - it is getting set as default value in autocomplete field, but even after getting updated the value is not changing.

I think that its because the autocomplete field is getting loaded before receiving data from the URL.

const [update, setUpdate] = useState([])
const [selectedMode, setSelectedMode] = useState([{ name: '' }])
const mode = [
    { name: 'Air' },
    { name: 'Train' },
    { name: 'Surface' }
]
useEffect(() => {
    axios
        .get(`http://127.0.0.1:8000/bill/${id}`)
        .then(response => {
            const data = response.data
            setUpdate(data)
            setSelectedMode([{ name: data.mode }])
        })
}, [])

return (
        <>
            <Autocomplete
                defaultValue={selectedMode.name ? selectedMode : null}
                options={mode}
                getOptionLabel={option => option.name}
                getOptionSelected={(option, value) => option.name === value.name}
                onChange={(e, value) => setUpdate({
                    ...update,
                    mode: value ? value.name : ''
                })}
                renderInput={params =>
                    <TextField
                        {...params}
                        required
                        label="Mode"
                        variant="outlined"
                    />}
            />
        <>
      )

The alternate way i tried is instead of setting defaultValue, I'm using - value={selectedMode} - and on onChange event I'm updating the value stored in selectedMode. But this also didn't give me desired output.

Below is the code :-

const [update, setUpdate] = useState([])
const [selectedMode, setSelectedMode] = useState([{ name: '' }])
const mode = [
    { name: 'Air' },
    { name: 'Train' },
    { name: 'Surface' }
]
useEffect(() => {
    axios
        .get(`http://127.0.0.1:8000/bill/${id}`)
        .then(response => {
            const data = response.data
            setUpdate(data)
            setSelectedMode([{ name: data.mode }])
        })
}, [])

return (
        <>
            <Autocomplete
                value={selectedMode.name}
                options={mode}
                getOptionLabel={option => option.name}
                getOptionSelected={(option, value) => option.name === value.name}
                onChange={(e, value) => setSelectedMode([{
                    ...selectedMode,
                    name: value ? value.name : ''
                }])}
                renderInput={params =>
                    <TextField
                        {...params}
                        required
                        label="Mode"
                        variant="outlined"
                    />}
            />
        <>
      )

Warning I'm getting while no option is selected :- screenshot of the warning -- warning

warning --

react_devtools_backend.js:6 Material-UI: The value provided to Autocomplete is invalid.
None of the options match with `{"name":""}`.
You can use the `getOptionSelected` prop to customize the equality test. 
    at Autocomplete (http://localhost:3000/static/js/0.chunk.js:41722:35)
    at WithStyles (http://localhost:3000/static/js/0.chunk.js:47043:31)
    at DetailData (http://localhost:3000/static/js/main.chunk.js:1311:86)
    at Route (http://localhost:3000/static/js/0.chunk.js:90811:29)
    at Switch (http://localhost:3000/static/js/0.chunk.js:91013:29)
    at App (http://localhost:3000/static/js/main.chunk.js:207:75)
    at Router (http://localhost:3000/static/js/0.chunk.js:90448:30)
    at BrowserRouter (http://localhost:3000/static/js/0.chunk.js:90082:35)
1
  • But this also didn't give me desired output. why? Commented Jul 5, 2020 at 6:30

2 Answers 2

2

Your second solution should work, but here are a few changes you should make:

Since you can only select on at a time there's no reason to wrap the mode in an array, in fact your code will fail, since array doesn't have a name property.

The value should be one item of the options array, pass the actual object, not just the name property. You shouldn't use a dummy object for no selection, use null instead.

Your code should look like this:

const [update, setUpdate] = useState([])
const [selectedMode, setSelectedMode] = useState(null)
const mode = [
    { name: 'Air' },
    { name: 'Train' },
    { name: 'Surface' }
]
useEffect(() => {
    axios
        .get(`http://127.0.0.1:8000/bill/${id}`)
        .then(response => {
            const data = response.data
            setUpdate(data)
            setSelectedMode({ name: data.mode })
        })
}, [])

return (
        <>
            <Autocomplete
                value={selectedMode}
                options={mode}
                getOptionLabel={option => option.name}
                getOptionSelected={(option, value) => option.name === value.name}
                onChange={(e, value) => setSelectedMode({
                    name: value ? value.name : ''
                })}
                renderInput={params =>
                    <TextField
                        {...params}
                        required
                        label="Mode"
                        variant="outlined"
                    />}
            />
        <>
      )
Sign up to request clarification or add additional context in comments.

6 Comments

This is working well, but I'm getting a warning if I'm clearing the selected value (i.e., no option is selected). I'm attaching the pic of warning in my question, check it out. And thanks for your valuable time :) @Mordechai
Didn't see the warning yet but assume it's about changing from controlled to uncontrolled. For no selection use null instead of undefined
Still getting the same warning on clearing the selected option. :( @Mordechai
You shouldn't be using that placeholder with an empty name. Just use null on no selection
If this answer was helpful please accept it (tap the check mark next to the answer) and upvote.
|
0

this just an idea, try to set a loading variable, then in the useEffect set it to false. Use this variable in a if to render your Autocomplete when loading is false.

const [update, setUpdate] = useState([])
const [selectedMode, setSelectedMode] = useState([{ name: '' }])
const [loading, setLoading] = useState(true)
const mode = [
{ name: 'Air' },
{ name: 'Train' },
{ name: 'Surface' }
]
useEffect(() => {
axios
    .get(`http://127.0.0.1:8000/bill/${id}`)
    .then(response => {
        const data = response.data
        setUpdate(data)
        setSelectedMode([{ name: data.mode }])
        setLoading(false)
    })
}, [])

I believe that when you are in the useEffect and set a value the return won't load it as you want it. Let me know if that works.

1 Comment

If I'm doing this, I'm getting no warning on page load, but whenever I'm clearing the value (i.e., clearing the selected value means no option is selected its giving me the same warning which I was getting before the modification you said. I'm adding the pic of the warning in my question, check it out! And thanks for your valuable time. :) @Jono Calvo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.