Iván Herrera
Iván Herrera

Reputation: 59

Pass selected option to parent component - react

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

Answers (2)

Ali Baykal
Ali Baykal

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>
  );
}

You can try the code here

Upvotes: 1

bas
bas

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>
  );
}

Sandbox Example

Upvotes: 0

Related Questions