Task: There is a select in option I print through the map the names (name) of the object and change the current state. After selecting the option I want to display the selected Option on the screen (<p>{this.props.valueSelect}</p>) , but it is not displayed.

Kompanent

 import React, { Component } from 'react' import Check from './conponent/Check' import List from './conponent/List' import './App.css'; class App extends Component { constructor(){ super(); this.state = { monument: [{ "id" : 1, "name": "Памятник №1", "color": ["Blue","Red", "White"], "width": 300, "heigth": 100, "price": 50, "country": "Russia", "url": "https://i.ibb.co/Nx8k7NJ/pam1.png" }, { "id" : 2, "name": "Памятник №2", "color": ["Blue","Red", "White"], "width": 300, "heigth": 100, "price": 50, "country": "Russia", "url": "https://i.ibb.co/Nx8k7NJ/pam1.png" }], valueSelect: " " } } render() { return ( <> <List monumentObj = {this.state.monument} valueSelect = {this.state.valueSelect} /> </> ); } } 

Component Select.js

 export default App; import React, { Component } from 'react'; export default class Select extends Component { handleChange = (e) => { this.setState({ valueSelect: e.target.value }, () => console.log(this.state.valueSelect)) this.forceUpdate(); } render () { return ( <select value = {this.props.valueSelect} onChange={this.handleChange} > { this.props.monumentObj.map(i => { return( <option key={i.id} value = {i.name}>{i.name}</option> ) }) } </select> ) }; } 

Component

 import React, { Component } from 'react'; import Collage from './Collage' import Select from './Select' export default class List extends Component { render() { return ( <div className="List"> <Select monumentObj = {this.props.monumentObj} /> <Collage monumentObj = {this.props.monumentObj} valueSelect = {this.props.valueSelect} /> </div> ); } } 

Component

 import React, { Component } from 'react'; export default class Collage extends Component { render () { return ( <div> { this.props.monumentObj.map(i => { return ( <> <h3>{i.name}</h3> <p>{this.props.valueSelect}</p> </> ) }) } </div> ) }; } 

    2 answers 2

    Your mistake is that you write the selected value to the state of the Select component, and display the value from the props inside your Collage component that belongs to the state of the App component.


    Solving the problem : transfer the handleChange method to the App component and pass it via props to the List component like this:

     class App extends Component { constructor(){ super(); this.state = { monument: [{ ... some values here ... } ], valueSelect: "", } this.handleChange = this.handleChange.bind(this); } handleChange = (e) => { this.setState({ valueSelect: e.target.value }, () => console.log(this.state.valueSelect)); } render() { return ( <> <List monumentObj = {this.state.monument} valueSelect = {this.state.valueSelect} onSelectValue = {this.handleChange} /> </> ); } } 

    In the List component, forward this method further to the Select component from where you previously rendered it:

     export default class List extends Component { render() { return ( <div className="List"> <Select monumentObj = {this.props.monumentObj} onSelectValue = {this.props.onSelectValue} /> <Collage monumentObj = {this.props.monumentObj} valueSelect = {this.props.valueSelect} /> </div> ); } } 

    And onChange your on onChange method to onChange this.props.onSelectValue like this:

     export default class Select extends Component { render () { return ( <select value = {this.props.valueSelect} onChange={this.props.onSelectValue} > { this.props.monumentObj.map(i => { return(<option key={i.id} value = {i.name}>{i.name}</option>) }) } </select> ) }; } 

    that is, the method from the List is invoked and transmitted via props from the App component.

      According to the documentation on the React property for the component can not be changed in the component.

      You need to transfer the handleChange method to the top level and descend this method as property to child components.

      Just remember to bind

      In the example below, I used 3 classes -

      • Parent class with handler
      • Child class that accepts a parent class state variable as a parameter
      • Child class that accepts a method for changing the state of a parent class as an argument

      When you click a button, a method is invoked that changes state in the parent class. This state, in turn, is reactively transmitted to the first child component, which displays the change of this state on the screen.

       class FirstComponent extends React.Component { render(){ var {selected} = this.props; return <h1> Selected - {selected} </h1> } } class ButtonWithCallback extends React.Component { render(){ var {handler} = this.props; return (<button onClick={() => {handler("This Button Rules!")}}> Click Me </button>); } } class App extends React.Component { constructor(props){ super(props) this.state = { selected: "" } this.handleSelect = this.handleSelect.bind(this); } handleSelect(newValue){ this.setState({selected: newValue}); } render() { var {selected} = this.state; return ( <div> <FirstComponent selected={selected}/> <ButtonWithCallback handler={this.handleSelect} /> </div> ); } } ReactDOM.render(<App />, document.getElementById('react-root')); 
       <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> <div id="react-root">