'How do I pass props from a child class to parent then to a (different) child class?
I'm trying to call getNumPlayers() to get the number of players in the input box in NumPlayers.js.
Then I want to pass that to Test.js and use it in that component. Is there a way to go about passing it directly or should I pass it via App.js, and if so how
App.js
import React, { useState } from 'react';
import NumPlayers from './NumPlayers';
import Title from "./Title";
import Test from "./Test";
import { Routes, Route, Link } from "react-router-dom";
export default function App() {
return (
<Routes>
<Route path="/" element={<><Title/><NumPlayers func={getNumPlayers}/></>} />
<Route path="/player-names" element={<Test />} />
</Routes>
)
}
NumPlayers.js
import React from 'react';
import history from './history';
import { Link, withRouter, BrowserHistory, useNavigate } from 'react-router-dom'
export default function NumPlayers(props) {
const navigate = useNavigate();
var numPlayers;
function getNumPlayers() {
numPlayers = (document.getElementById('numPlayersInput').value);
}
return (
<div>
<h1>
<input type="number" id="numPlayersInput"/>
<button onClick={() => {navigate('/player-names'); getNumPlayers();}}>Confirm</button>
</h1>
</div>
)
}
Test.js
import React from 'react';
import NumPlayers from './NumPlayers';
export default function Test(props) {
return (
<div>
<h1>
TEST
</h1>
<h2>
{numPlayers}
</h2>
</div>
)
}
Solution 1:[1]
We cannnot pass props from child to parent in reactjs. But there are many solutions and libraries for resolving this type and more scenarios like Redux,context api(react),etc But it depends on the need. In your scenario i will pass a call function from App.js file to your NumPlayers Component and gets its value in app.js then pass this value in props of Test component. In you App.js, create state before the return
const [num,setNum]= useState(0);
Now pass num and setNum function in props of your first component
<Route path="/" element={<><Title/><NumPlayers num={num} func={(val)=>setNum(val)}/>
</>} />
Now get this func in props of NumPlayers,And call it in onChange event of input box and set value attribute to props.num
<input type="number" value={props.num} onChange={(e)=>props.func(e.target.value)}
id="numPlayersInput"/>
Remove your getNumPlayers function and also reomve it from onClick button.
Now what you write in input box you are getting its value in app.js file in num. Now pass this num as props in Test component.
<Route path="/player-names" element={<Test num={num} />} />
Now get this num in props of Test Component
<h2>
{props.num}
</h2>
Solution 2:[2]
This is pretty rough and I did not test it, but no one has answered your question yet and this should point you in the right direction.
App.js
import React, { useState } from 'react';
import NumPlayers from './NumPlayers';
import Title from "./Title";
import Test from "./Test";
import { Routes, Route, Link } from "react-router-dom";
export default function App() {
// Create state to hold the number of players.
// This needs to be at a level higher than the routes as you wish to share the value over
// multiple different routes.
const [numberOfPlayers, setNumberOfPlayers] = useState(undefined);
return (
<Routes>
{/* Pass the state "numberOfPlayers" to the input component so that it can be used as an initial value for the input */}
{/* Pass the state setter "setNumberOfPlayers" to the input component so that it can update the state */}
<Route path="/" element={<><Title/><NumPlayers numberOfPlayers={numberOfPlayers} setNumberOfPlayers={setNumberOfPlayers}/></>} />
{/* Pass the state "numberOfPlayers" to the view component so that it can be displayed */}
<Route path="/player-names" element={<Test numberOfPlayers={numberOfPlayers} />} />
</Routes>
)
}
NumPlayers.js
import React, { useRef } from 'react';
import history from './history';
import { useNavigate } from 'react-router-dom'
export default function NumPlayers({ numberOfPlayers, setNumberOfPlayers }) {
const navigate = useNavigate();
// create a ref for the input (used to get a reference to the DOM object of the input)
const inputRef = useRef();
return (
<div>
<h1>
{/* set the default (initial) value of the input to the current number of players */}
<input type="number" id="numPlayersInput" ref={inputRef} defaultValue={numberOfPlayers} />
<button
onClick={(e) => {
// check to make sure a value was entered.
if (inputRef.current?.value === undefined) {
alert('A value must be entered!');
return;
}
// set the number of players state to the new value.
setNumberOfPlayers(inputRef.current.value);
navigate('/player-names');
}}
>
Confirm
</button>
</h1>
</div>
)
}
Test.js
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
export default function Test({ numberOfPlayers }) {
const navigate = useNavigate();
// every time number of players is updated check to make sure a value is present,
// otherwise redirect to input page
// State will not be stored across a browser refresh or route, but using the in app routing
// will allow for the state to be kept.
useEffect(() => {
if (numberOfPlayers === undefined) {
navigate('/');
}
}, [numberOfPlayers])
return (
<div>
<h1>
TEST
</h1>
<h2>
{numberOfPlayers}
</h2>
</div>
)
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | RoshaanAli |
| Solution 2 | Jacob Smit |
