Suppose the state drive needs to be present in the Parent and the Child. Then you define it in the parent and create a callback function responsible for changing this state setDrive.
In general, the state must be defined at closest common ancestor between the components that use or change this state and this is called Lifting State Up. In your case, something like this (complete demo):
Parent:
const VehicleList = () => {
const classes = useStyles();
const [drive, setDrive] = React.useState(null); // the lifted state
const sendDataToParent = (index) => { // the callback. Use a better name
console.log(index);
setDrive(index);
};
return (
<div className={classes.root}>
{vehicleData.map((vehicle) => (
<div
key={vehicle.name}
style={{
width: "20rem",
border: vehicle.name === drive ? "1px solid red" : null
}}
>
<Vehicle vehicle={vehicle} sendDataToParent={sendDataToParent} />
</div>
))}
</div>
);
};
Child:
const Vehicle = ({ vehicle, sendDataToParent }) => {
const classes = useStyles();
const [showDriveAction, setShowDriveAction] = React.useState(false);
const driveURL = React.useState("");
return (
<Paper className={classes.root} elevation={3}>
<Grid container spacing={2}>
{/* ... */}
<CardActions>
<Button
onClick={() => {
sendDataToParent(vehicle.name);
}} //this is where it needs to be passed
size="small"
color="secondary"
startIcon={<FolderOpenIcon />}
style={{ fontWeight: "bold" }}
>
{/* ... */}
</CardActions>
</Grid>
</Paper>
);
};
Answer from Rodrigo Amaral on Stack OverflowSuppose the state drive needs to be present in the Parent and the Child. Then you define it in the parent and create a callback function responsible for changing this state setDrive.
In general, the state must be defined at closest common ancestor between the components that use or change this state and this is called Lifting State Up. In your case, something like this (complete demo):
Parent:
const VehicleList = () => {
const classes = useStyles();
const [drive, setDrive] = React.useState(null); // the lifted state
const sendDataToParent = (index) => { // the callback. Use a better name
console.log(index);
setDrive(index);
};
return (
<div className={classes.root}>
{vehicleData.map((vehicle) => (
<div
key={vehicle.name}
style={{
width: "20rem",
border: vehicle.name === drive ? "1px solid red" : null
}}
>
<Vehicle vehicle={vehicle} sendDataToParent={sendDataToParent} />
</div>
))}
</div>
);
};
Child:
const Vehicle = ({ vehicle, sendDataToParent }) => {
const classes = useStyles();
const [showDriveAction, setShowDriveAction] = React.useState(false);
const driveURL = React.useState("");
return (
<Paper className={classes.root} elevation={3}>
<Grid container spacing={2}>
{/* ... */}
<CardActions>
<Button
onClick={() => {
sendDataToParent(vehicle.name);
}} //this is where it needs to be passed
size="small"
color="secondary"
startIcon={<FolderOpenIcon />}
style={{ fontWeight: "bold" }}
>
{/* ... */}
</CardActions>
</Grid>
</Paper>
);
};
Passing data from child to parent in functional components React
const Parent = (props) => {
let onClickFunction = (arg) => alert(arg);
return <Child update={onClickFunction} />
}
const Child({ update }) {
return <button onClick={() => update(1)}> Click </button>;
}
export default Parent;
This should work. While sending the prop back you are sending that as an object rather send that as a value or alternatively use it as an object in the parent component. Secondly you need to format your json object to contain name value pairs and use valueField and textField attribute of DropdownList
Short Answer
Parent:
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
Child:
handleLangChange = () => {
var lang = this.dropdown.value;
this.props.onSelectLanguage(lang);
}
Detailed:
EDIT:
Considering React.createClass is deprecated from v16.0 onwards, It is better to go ahead and create a React Component by extending React.Component. Passing data from child to parent component with this syntax will look like
Parent
class ParentComponent extends React.Component {
state = { language: '' }
handleLanguage = (langValue) => {
this.setState({language: langValue});
}
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
)
}
}
Child
var json = require("json!../languages.json");
var jsonArray = json.languages;
export class SelectLanguage extends React.Component {
state = {
selectedCode: '',
selectedLanguage: jsonArray[0],
}
handleLangChange = () => {
var lang = this.dropdown.value;
this.props.onSelectLanguage(lang);
}
render() {
return (
<div>
<DropdownList ref={(ref) => this.dropdown = ref}
data={jsonArray}
valueField='lang' textField='lang'
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
}
Using createClass syntax which the OP used in his answer
Parent
const ParentComponent = React.createClass({
getInitialState() {
return {
language: '',
};
},
handleLanguage: function(langValue) {
this.setState({language: langValue});
},
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
);
});
Child
var json = require("json!../languages.json");
var jsonArray = json.languages;
export const SelectLanguage = React.createClass({
getInitialState: function() {
return {
selectedCode: '',
selectedLanguage: jsonArray[0],
};
},
handleLangChange: function () {
var lang = this.refs.dropdown.value;
this.props.onSelectLanguage(lang);
},
render() {
return (
<div>
<DropdownList ref='dropdown'
data={jsonArray}
valueField='lang' textField='lang'
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
});
JSON:
{
"languages":[
{
"code": "aaa",
"lang": "english"
},
{
"code": "aab",
"lang": "Swedish"
},
]
}
To pass data from child component to parent component
In Parent Component:
getData(val){
// do not forget to bind getData in constructor
console.log(val);
}
render(){
return(<Child sendData={this.getData}/>);
}
In Child Component:
demoMethod(){
this.props.sendData(value);
}
How can I send data from a child to a parent functional component in ReactJS?
reactjs - pass data from child to parent in functional components - Stack Overflow
i don't understand how child-to-parent component communication works.
Using callback function to pass data from child to parent component
Videos
It is anti-pattern in React to store passed props into local state, so you don't really need the numOriginalServings state in PreInputs. Pass originalServings to PreInputs to be used as the default value of the input and pass the updated input value back to the parent component.
PreInputs
const PreInputs = (props) => {
const handleOriginalServingsChange = (e) => {
const originalServings = e.target.value;
props.changeOriginalServings(originalServings);
};
return (
<div className="pre-inputs">
<form>
<label>Original Servings: </label>
<input
defaultValue={props.originalServings} // <-- initialize input
onChange={handleOriginalServingsChange}
type="number"
/>
</form>
<h1>Placeholder</h1>
</div>
);
};
Parent
function App() {
//define variables using states
const [numIngredients, setNumIngredients] = useState(5);
const [originalServings, setOriginalServings] = useState(8);
const [newServings, setNewServings] = useState(4);
//create handling functions for the variables
const handleNumIngredients = (num) => {
setNumIngredients(num);
};
const handleOriginalServings = (num) => {
setOriginalServings(num);
};
const handleNewServings = (num) => {
setNewServings(num);
};
return (
<div>
<Header title="test"/>
<h1>{originalServings}</h1>
<PreInputs
originalServings={originalServings} // <-- pass state
changeOriginalServings={handleOriginalServings} // <-- pass callback
/>
</div>
);
}
if you want to send data to the parent component
you have 3 ways for it
1- use redux
2- use context
3- make function in the parent component and get data in this function and sent function to the child component