0

I'm working on a form where some additional inputs will be shown based on the value of select. The value of select changes on selecting a different option, but the "numberOfUsers" text field does not become visible.

I can see the changed value being printed on the console. Yes is printed on selecting first option and No on selecting the select.

I don't understand why it doesn't work. Please let me know the mistakes I have done.

Below is the code I have written

import React from 'react'
import { useState } from 'react'
import { Grid } from '@mui/material'
import './Form.css'

export const AddStartupForm = () => {

    const [fields, setFields] = useState({})

    function handleChange(event) {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;
        
        fields[name] = value
        setFields(fields)
        console.log(fields['revenueGenerated'])
    }

    
    return (
        <Grid container sx={{py: 5}}>
        <Grid item xs={1} sm={4}></Grid>
        <Grid item xs={10} sm={4}>
            <form>
                <label htmlFor="startupName">Startup Name</label>
                <input type="text" 
                    name="startupName"                     
                    onChange={handleChange}
                    value={fields["startupName"]}
                />

                <label htmlFor="countryName">Country</label>                
                <input type="text" 
                    name="countryName"                     
                    onChange={handleChange}
                    value={fields["countryName"]}
                />            

                <label htmlFor="revenueGenerated">Do you make revenue?</label>
                <select name="revenueGenerated"
                    onChange={handleChange}
                    value={fields["revenueGenerated"]}
                >
                    <option disabled selected value=''> -- select an option -- </option>
                    <option value="Yes">Yes</option>
                    <option value="No">No</option>
                </select>

                { fields['revenueGenerated'] === 'Yes' ?
                   <>
                       <label htmlFor="numberOfUsers">Sample Yes</label>
                       <input type="text"
                           name="numberOfUsers"
                       />
                   </>
                   : null
               } 
                
            </form>            
        </Grid>
        </Grid>
    )
}


3
  • What is printed in console if you change the select, please include all relevant data in Question. Commented Dec 15, 2021 at 15:32
  • As setting any state is asynchronous, so console might print older value, try to console.log value directly Commented Dec 15, 2021 at 15:35
  • @SayyedDawood I can see the selected value being printed on the console. Yes is printed when I select the first option and No on selecting the second. Commented Dec 15, 2021 at 15:39

2 Answers 2

1

fields is an object and updating a prop on that object does not change the reference to the object so react's equality check will not recognize a change (and therefore won't rerender).

Try changing

        fields[name] = value
        setFields(fields)

to

        setFields({...fields, [name]: value})
Sign up to request clarification or add additional context in comments.

Comments

0

The state isn't updated, because the reference of the state doesn't change. You can try that by adding a console.log before your return statement:

  console.log(fields);

  return (...)

It never changes.

Try setting your fields like this:

function handleChange(event) {
    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = target.name;

    
    setFields({
      ...fields,
      [name]: value
    });
  }

If you change your handler to use useCallback, be sure to add the fields as a dependency, so it get's changed:

const handleChange((event) => { 

    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = target.name;


    setFields({
      ...fields,
      [name]: value
    });


 }, [fields]);

1 Comment

Thanks, it works as expected now.

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.