Passing field value from Child to Parent Component onChange with React - reactjs

I am working on a project with React for the first time. What I am trying to do is send a Child component's value that is within an input field to a variable in its Parent. More precisely, I would like the value to be transmitted whenever the value in the input field is changed. Here is a basic overview of what I have (simplified):
const Parent = () => {
const handleSubmit = (e) => {
e.preventDefault();
// Series of variables to hold the values from Child2
}
return (
<div>
<form onSubmit={handleSubmit}>
<div>
<Child1 name="child1"/>
<Child1 name="child2"/>
</div>
<button>Submit</button>
</form>
</div>
);
}
const Child1 = () => {
return (
<div>
<Child2 name="childchild1"/>
<Child2 name="childchild2"/>
<Child2 name="childchild3"/>
</div>
);
}
const Child2 = () => {
return (
<div>
<input type="number" .......></input>
</div>
);
}
In brief, my goal is to have the values from the input fields in the component Child2 to be transmitted to some array of values in Parent. That being said, I have looked at multiple ways of lifting up values in React online, but I haven't found something similar to my scenario. What would be the best way of proceeding? Thanks!

I think you can use useContext feature from react. so it is basically a way to manage state globally and you can share state between deeply nested components. so I'm thinking to make a function on the Parent that can be used from nested child to get value, you can use onChange method for instance
import { createContext, useContext } from "react";
const UserContext = createContext();
const Parent = () => {
const handleSubmit = (e) => {
e.preventDefault();
// Series of variables to hold the values from Child2
};
const handleInput = (data) => {
console.log(`this is data ${data.target.value}`);
};
return (
<UserContext.Provider value={handleInput}>
<div>
<form onSubmit={handleSubmit}>
<div>
<Child1 name="child1" />
<Child1 name="child2" />
</div>
<button>Submit</button>
</form>
</div>
</UserContext.Provider>
);
};
const Child1 = () => {
return (
<div>
<Child2 name="childchild1" />
<Child2 name="childchild2" />
<Child2 name="childchild3" />
</div>
);
};
const Child2 = () => {
const handleInput = useContext(UserContext);
return (
<div>
<input type="number" onChange={(e) => handleInput(e)}></input>
</div>
);
};
export default Parent;
perhaps this link can help you useContext

you can send a function from parent to child 1 then to child2, in this case we gonna send this function handleGetDataFromParent={getDataFromParent}
const Parent = () => {
const handleSubmit = (e) => {
e.preventDefault();
// Series of variables to hold the values from Child2
}
const getDataFromParent=(data)=>{
console.log('DATA from Child2', data)
}
return (
<div>
<form onSubmit={handleSubmit}>
<div>
<Child1 name="child1" handleGetDataFromParent={getDataFromParent}/>
<Child1 name="child2" handleGetDataFromParent={getDataFromParent}/>
</div>
<button>Submit</button>
</form>
</div>
);
}
const Child1 = ({handleGetDataFromParent}) => {
return (
<div>
<Child2 name="childchild1" handleGetDataFromParent={handleGetDataFromParent}/>
<Child2 name="childchild2" handleGetDataFromParent={handleGetDataFromParent}/>
<Child2 name="childchild3" handleGetDataFromParent={handleGetDataFromParent}/>
</div>
);
}
const Child2 = ({handleGetDataFromParent}) => {
const setNumber=(number)=>{
handleGetDataFromParent(number)
}
return (
<div>
<input type="number" onChange={(n)=>setNumber(n)}.......></input>
</div>
);
}

Related

Passing Data from Parent to Child Component's Input Field in ReactJS

I am working on a personal project in React for the first time. It has a structure of the following form (the following is simplified):
const Parent = () => {
const handleSubmit = (e) => {
e.preventDefault();
// Series of variables to hold the values from Child2
}
return (
<div>
<form onSubmit={handleSubmit}>
<div>
<Child1 name="child1"/>
<Child1 name="child2"/>
</div>
<button>Submit</button>
</form>
</div>
);
}
const Child1 = () => {
return (
<div>
<Child2 name="childchild1"/> // Child 2 components are individual inputs fields
<Child2 name="childchild2"/>
<Child2 name="childchild3"/>
</div>
);
}
const Child2 = () => {
return (
<div>
<input type="number" .......></input>
</div>
);
}
Basically put, I would like to add an import button in my Parent component which will fill the fields found in the Child2 Components. My question is: How would I go about passing the values from my Parent component to my Child2 Components so that they fill their input fields? I am looking for a relatively clean solution if possible. Thanks!
Component are build to be reusable. The clean way is to pass value from Child2 to Parent through Child 1.
const Parent = () => {
const [state1, setState1] = useState({})
const [state2, setState2] = useState({})
const handleSubmit = (e) => {
e.preventDefault();
// Series of variables to hold the values from Child2
}
return (
<div>
<form onSubmit={handleSubmit}>
<div>
<Child1 value={state1} onChange={setState1} name="child1"/>
<Child1 value={state2} onChange={setState2} name="child2"/>
</div>
<button>Submit</button>
</form>
</div>
);
}
const Child1 = ({ value, onChange }) => {
return (
<div>
<Child2 value={value.substate1} onChange={v=>onChange({...value, substate1: v})} name="childchild1"/> // Child 2 components are individual inputs fields
<Child2 value={value.substate2} onChange={v=>onChange({...value, substate2: v})} name="childchild2"/>
<Child2 value={value.substate3} onChange={v=>onChange({...value, substate3: v})} name="childchild3"/>
</div>
);
}
const Child2 = ({ value, onChange }) => {
return (
<div>
<input value={value} onChange={onChange} type="number" .......></input>
</div>
);
}
If that answer is unacceptable for you, you can have a look to redux or react context, but that breaks the reusability of the component and thats not "clean"

Pass input to React sibling

I'm having trouble passing data between two React siblings. I need to have an input component that will receive and pass the input to sibling that will handle the input and perform some logic.
I get to receive the data in the parent, but I cannot seem to get the passing to the sibling to work...
This is the wrapper/parent
const [corpBrandId, setCorpBrandId] = useState("");
const [secondInput, setSecondInput] = useState("");
const handleCorpBrandIdChange = ({ target }) => {
setCorpBrandId(target.value);
};
const handleSecondInputChange = ({ target }) => {
setSecondInput(target.value);
};
const handleClick = () => {
// console.log(corpBrandId);
// console.log(secondInput);
};
return (
<div className="App">
<InputField
label="Corporate brand ID "
onChange={handleCorpBrandIdChange}
value={corpBrandId}
/>
<TableConnect corpBrandId={corpBrandId} secondInput={secondInput} />
<InputField
label="Second input param"
onChange={handleSecondInputChange}
value={secondInput}
/>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default MainWrapper;
And here's the input component:
return (
<div>
<label>{label}</label>
<input type="text" value={value} name={name} onChange={onChange} />
</div>
);
};
export default InputField;
I've got no working or remotely close code how to receive the data...
This doesn't work in the sibling:
return (
<div>
Test
{props.corpBrandId}
{props.secondInput}
</div>
);
}
Anyone got any idea?
Based on your comment to #Shahar's answer, it sounds like you maybe haven't defined props in your TableConnect component. It should look something like this:
const TableConnect = (props) => {
return (
<div>
Test
{props.corpBrandId}
{props.secondInput}
</div>
);
};
Here's a codesandbox where TableConnect is correctly receiving the input from your input fields: https://codesandbox.io/s/throbbing-cloud-wgub8?file=/src/App.js
export default InputField;
return (
<div>
Test
{props.corpBrandInput} //shouldnt it be: corpBrandId
{props.inputText} //shouldnt it be: secondInput
</div>
);
}

Pass hook or function to a child component

What is the preferred way to change state in React using Hooks?
Option 1: I think this is the more "traditional"
function App() {
const [input, setInput] = useState('');
const onInputChange = (event) => {
setInput(event.target.value)
};
return (
<div className='App'>
<Form onInputChange={onInputChange} />
</div>
);
}
const Form = ({ onInputChange }) => {
return (
<div>
<div>
<div>
<input
type='text'
onChange={onInputChange}
/>
<button'>
Submit
</button>
</div>
</div>
</div>
);
};
export default Form;
Option 2: But I have seen people do this
function App() {
const [input, setInput] = useState('');
return (
<div className='App'>
<Form onInputChange={setInput} />
</div>
);
}
export default App;
const Form = ({ onInputChange }) => {
return (
<div>
<div>
<div>
<input
type='text'
onChange={(e) => {
onInputChange(e.target.value);
}}
/>
<button>
Submit
</button>
</div>
</div>
</div>
);
};
export default Form;
In Option 1 in the App component the logic to change it's state is there.
In Option 2, the logic to change App component is in a child component, right?
If I understand correctly, I think Option 1 makes more sense. What do you think?
option 1 is better because we only have to pass the props or data to child component not the logic , Logic must be reside in parent component.

How to pass a function to a child component and use as an useState?

Hello i have an component where i set a prop darkMode in a useState. I want to give this to the child component with onDarkmodeChange={darkMode}. This child gave this prop also to his child. In the toggle switch i want to use the prop onDarkmodeChange. But how am i supposed to use this? I tink i am doing something wrong because darkMode is not updated anymore.
export function PageLayout({ children }) {
const [darkMode, setDarkMode] = React.useState(false)
return (
<Header onDarkModeChange={darkMode} />
)
}
export function Header({ onDarkModeChange }) {
return (
<ToggleSwitch {... { onDarkModeChange }} />
)
}
export function ToggleSwitch({ onDarkModeChange }) {
const [isToggled, setIsToggled] = React.useState(onDarkModeChange)
return (
<label className={styles.component}>
<input className={styles.input} type='checkbox' checked={isToggled} onChange={() => setIsToggled(!isToggled)} />
<span className={cx(styles.switch, isToggled && styles.isActive)} />
</label>
)
}
I think it's not necessary to have the isToggled state since it's going to have the same value that the darkMode state. Also, I would move all the logic to the parent so that both children can access and manipulate that state, in case that it's necessary. Try this:
export function PageLayout({ children }) {
const [darkMode, setDarkMode] = React.useState(false)
const switchDarkMode = () => {
setDarkMode(currentDarkMode => !currentDarkMode)
}
return (
<Header darkMode={darkMode} switchDarkMode={switchDarkMode} />
)
}
export function Header({ darkMode, switchDarkMode }) {
return (
<ToggleSwitch darkMode={darkMode} switchDarkMode={switchDarkMode} />
)
}
export function ToggleSwitch({ darkMode, switchDarkMode }) {
return (
<label className={styles.component}>
<input className={styles.input} type='checkbox' checked={darkMode} onChange={switchDarkMode} />
<span className={cx(styles.switch, darkMode && styles.isActive)} />
</label>
)
}

How to set focus on child component's input on a button click in the parent in React Hooks

I have a parent component that has a button with an onClick event and when there is an error I want to focus on an input that is in a child component. I know this can be done using useRef but I keep getting an undefined error. Here is my code:
/* Parent Component */
const parent = () => {
const acresRef = useRef();
const addrRef = useRef();
const acresFocus = () => {
acresRef.current.focus();
};
const addressFocus = () => {
addrRef.current.focus();
};
return (
<Child addrRef={addrRef} acresRef={acresRef} />
<button onClick={acresFocus} />
<button onCLick={addressFocus} />
)
}
/*Child Component*/
const Child = forwardRef(
({props}, acresRef, addrRef) => (
<div>
<label for="address">Address</label>
<input type="text" name="address" ref={addrRef} />
</div>
<div>
<label for="acres">Acres</label>
<input type="text" name="acres" ref={acresRef} />
</div>
)
);
You are incorrectly using refs here. forwardRef works when ref is passed to the component. Anything apart from that is a prop to the component. So in your case, acresRef and addrRef will be received within props by the child component.
/*Child Component*/
const Child = (props) => (
<>
<div>
<label htmlFor="address">Address</label>
<input type="text" name="address" ref={props.addrRef} />
</div>
<div>
<label htmlFor="acres">Acres</label>
<input type="text" name="acres" ref={props.acresRef} />
</div>
</>
);
/* Parent Component */
const Parent = () => {
const acresRef = React.useRef();
const addrRef = React.useRef();
const acresFocus = () => {
acresRef.current.focus();
};
const addressFocus = () => {
addrRef.current.focus();
};
return (
<>
<Child addrRef={addrRef} acresRef={acresRef} />
<button onClick={acresFocus}>acres</button>
<button onClick={addressFocus}>address</button>
</>
);
};
Check this codesandbox here.
You may also just bind the props like so :
const Child = (props) => {
const onClick = props.onClick;
return(<div><p>
{onClick()}
</p>
</div>
);
}
/* Parent Component */
const ParentEl = () => {
const onClick = ()=>{return "hi"};
return (
<div>
<Child onClick={onClick} />
</div>
)
}
/*Child Component*/
export default function App() {
return (
<div className="App">
<ParentEl />
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
or a codesandbox link to see directly what it does :
https://codesandbox.io/s/hidden-water-s8qjj?file=/src/App.js
here :
const onClick = props.onClick;
in the child component is doing all the magic

Resources