Search code examples
javascriptreactjsjsondestructuring

Lifting the state from child to parent with React 18


I want to capture the data in my UserInput component and bring it back to the App.jsx and store it in the state.

My investment object looks like

const [initialInvestment, setInitialInvestment] = useState({
        initialInvestment: 100,
        annualInvestment: 200,
        expectedReturn: 3.3,
        duration: 4
    });

The object looks like

{
    initialInvestment: 100,
    annualInvestment: 200,
    expectedReturn: 3.3,
    duration: 4
}

My JSX code for the component UserInput.jsx

    <div id={'user-input'}>
        <div className={'input-group'}>
            <div>
                <label>Initial Investment</label>
                <input type={'number'} defaultValue={investment.initialInvestment} onKeyDown={event => onInvestmentUpdate(event)} required/>
            </div>
            <div>
                <label>Annual Investment</label>
                <input type={'number'} defaultValue={investment.annualInvestment} onKeyDown={event => onInvestmentUpdate(event)} required/>
            </div>
            <div>
                <label>Expected Return</label>
                <input type={'number'} defaultValue={investment.expectedReturn} onKeyDown={event => onInvestmentUpdate(event)} required/>
            </div>
            <div>
                <label>Duration</label>
                <input type={'number'} defaultValue={investment.duration} onKeyDown={event => onInvestmentUpdate(event)} required/>
            </div>
        </div>
    </div>

I need to lift the state from the UserInput and bring it to App.jsx

App.jsx

const investmentHandler = (investment) => {
    //const newInvestment = [...initialInvestment, ...investment];
    setInitialInvestment(prevInvestment => {
        return {
            ...prevInvestment,
            investment
        }
    });
}

        <UserInput init={initialInvestment} onUpdate={investmentHandler}/>

Solution

  • UserInput.jsx

        <section id={'user-input'}>
            <div className={'input-group'}>
                <p>
                    <label>Initial Investment</label>
                    <input type={'number'} name={'initialInvestment'} value={investment.initialInvestment} onChange={event => onUpdate('initialInvestment', event.target.value)} required/>
                </p>
                <p>
                    <label>Annual Investment</label>
                    <input type={'number'} name={'annualInvestment'} value={investment.annualInvestment} onChange={event => onUpdate('annualInvestment', event.target.value)} required/>
                </p>
                <p>
                    <label>Expected Return</label>
                    <input type={'number'} name={'expectedReturn'} value={investment.expectedReturn} onChange={event => onUpdate('expectedReturn', event.target.value)} step={'0.1'} required/>
                </p>
                <p>
                    <label>Duration</label>
                    <input type={'number'} name={'duration'} value={investment.duration} onChange={event => onUpdate('duration', event.target.value)} required/>
                </p>
            </div>
        </section>
    

    App.jsx

    const handleChange = (inputIdentifier, newValue) => {
        setUserInput(previousUserInput => {
            return {
                ...previousUserInput,
                [inputIdentifier]: newValue
            };
        });
    }
    
    <UserInput investment={userInput} onUpdate={handleChange}/>