Reputation: 59
I'm currently passing select options in a prop to my child component which comes from the parent options, but I've been struggled when passing the selection value back to the parent, this is what I have:
class ResultModel extends Component {
constructor(props) {
super(props);
this.state = {
brands: ['BMW', 'Mercedes', 'Chevrolet', 'Nissan'],
};
}
render() {
return (
<div>
<div className="cars-result-content__filters">
<WebFilter
brand={this.state.brands}
/>
</div>
</div>
)
}
}
In the child:
const handleChange = (event) => {
console.log('selected-brand', event.target.value)
};
function WebFilter(props) {
const {brand} = props;
return (
<div className="filter-web-section">
<Form.Group controlId="exampleForm.ControlSelect1">
<Form.Control onChange={handleChange} as="select">
{brand.map((item) => (
<option value ={item.value}>{item}</option>
))}
</Form.Control>
</Form.Group>
</div>
)
}
How can I send the selected value on the list back to the parent? Thanks in advance for any hint or help.
Upvotes: 1
Views: 2200
Reputation: 324
In general props are passed from parent to child. To communicate into the other direction you have to use callbacks and events. Like in:
import { useCallback } from "react";
export default function App() {
return (
<Select
optionData={[
{ value: "0", text: "first option" },
{ value: "1", text: "second option" }
]}
// hnadle selecting a different option
onChange={(data) => console.log(data)}
/>
);
}
// Creates a function to handle the change event dispatched by the select element
const createChangeHandler = callback => event => {
if (typeof callback === "function") {
const select = event.target;
const selectedIndex = select.selectedIndex;
const selectedOption = select.options[selectedIndex];
const value = selectedOption.value;
const text = selectedOption.innerText;
callback({ value, text });
}
};
function Select(props) {
const { optionData, onChange: _onChange } = props;
// onChange will be called when the select dispatches a change event
const onChange = useCallback(createChangeHandler(_onChange), [_onChange]);
return (
<select onChange={onChange}>
{optionData.map((data) => {
const { value, text } = data;
return (
<option key={value} value={value}>
{text}
</option>
);
})}
</select>
);
}
Upvotes: 1
Reputation: 15462
You can create a function that updates the parent's state and pass that function to the child, which the child can call via the onChange
of the Form
component:
import { Component } from "react";
import { Form } from "react-bootstrap";
class ResultModel extends Component {
constructor(props) {
super(props);
this.state = {
brands: ["BMW", "Mercedes", "Chevrolet", "Nissan"],
selectedBrand: ""
};
this.handleSelectedBrand = this.handleSelectedBrand.bind(this);
}
handleSelectedBrand(e) {
console.log(e.target.value); // Selected brand
this.setState({ selectedBrand: e.target.value });
}
render() {
return (
<div>
<div className="cars-result-content__filters">
<WebFilter
brand={this.state.brands}
handleSelectedBrand={this.handleSelectedBrand}
/>
</div>
</div>
);
}
}
function WebFilter(props) {
const { brand, handleSelectedBrand } = props;
return (
<div className="filter-web-section">
<Form.Group controlId="exampleForm.ControlSelect1">
<Form.Control as="select" onChange={handleSelectedBrand}>
{brand.map((item, key) => (
<option key={key}>{item}</option>
))}
</Form.Control>
</Form.Group>
</div>
);
}
Upvotes: 0