I have a parent component which maps through my array and prints out various iterations of my Child components.
I’m trying to access the state in the parent component but can’t figure out how to lift the correct state of "inputValue" from the child and have it in the parent instead.
Ideally I’d like the inputValue and isValidated state living in the PARENT so I can use it for various form-based functions.
Parent Component:
import React, { useState } from 'react';
import { formFieldsData } from './FormFields';
import Input from './Input';
export default function Form() {
return (
<form>
{formFieldsData.map((item) => (
<Input
key={item.id}
id={item.id}
label={item.label}
type={item.type}
placeholder={item.placeholder}
/>
))}
</form>
)
}
Child component:
import React, { useState } from 'react';
import styles from './forms.module.scss';
import RangeInput from './RangeInput';
export default function Input({ type, id, placeholder = '', label, props }) {
const [inputValue, setInputValue] = useState('');
const [isValidated, setIsValidated] = useState(false);
const isRangeInput = type === 'range';
const handleChange = (e) => {
setInputValue(e.target.value)
if(inputValue.length > 0 || type === 'date') {
setIsValidated(true)
}
}
return (
<div className={styles.form__row}>
<label htmlFor={id}>{label}: {inputValue}</label>
{isRangeInput
? <RangeInput id={id} onChange={(e) => handleChange(e)} />
: <input
required
type={type}
id={id}
name={id}
placeholder={placeholder}
className={styles.input}
value={inputValue}
onChange={(e) => handleChange(e)}
/>
}
<button type="submit" id="formSubmit" onClick={() => alert('button click catched')} disabled={!isValidated}>Submit!</button>
</div>
)
}
2
Answers
The easiest way for this is to manage your state in the parent. Then you just need to pass a function to your child as a prop to update the parent’ state. Here is one of my previous answer related to this problem and demonstrating how to apss data from child to parent.
Note that you should do this kind of prop drilling only when it’s a direct child. If your tree expand between parent and child then a context/state management would be more apropriate.
a) Just add the following function in your parent component.
b) Now, pass the inputDataHandler function using props to your child component.
c) Now, just call the inputDataHandler function with the arguments from child component by the handleChange function. Arguments can be value/state etc. Here, I have passed "inputValue" as argument.
The concept is, you write & pass the function as props to the child, when child calls that function with arguments, those arguments are passed to parent component. In this way, a value can be passed from child to parent. This concept is called "Lifting state up".