there are two components of the same level, I need to pass the value that was obtained in the NavigationBar component in the SearchLine component

import React from 'react'; import NavigationBar from '../NavigationBar/NavigationBar'; import MainComponent from '../MainComponent/MainComponent'; class BaseComponent extends React.Component { render() { return( <> <NavigationBar /> <MainComponent /> </> ); } } export default BaseComponent; 

the SearchLine component is contained in the MainComponent

 import React from 'react'; import { Route, Redirect, Switch } from 'react-router'; import SearchLine from '../MainComponent/SearchLine/SearchLine'; class MainComponent extends React.Component { render() { return( <> <Switch> <Route exact path="/all_songs/" component={SearchLine} /> <Route path="/"> <Redirect to="/all_songs/" /> </Route> </Switch> </> ); } } export default MainComponent; 

here is the NavigationBar component

 import React from 'react'; import { Link } from 'react-router-dom'; import './NavigationBar.css'; class NavigationBar extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {artName: ''}; } handleChange(e) { this.setState({artName: e.target.value}); } render() { const artistName = this.state.artistName; return( <div className="navBlock"> <img src={require('./search-solid.svg')} width={17} height={17} className="navImage"/> <input placeholder="Type in to Search..." className="input-title" value={artistName} onChange={this.handleChange} /> <div className="navContainer"> <ul> <Link to="/all_songs">All Songs</Link> </ul> </div> <div className="container"> <ul> <Link to="/albums">Albums</Link> </ul> </div> </div> ); } } export default NavigationBar; 

I do not understand how I can correctly take from NavigationBar the value that was entered into the input and transfer it to SearchLine

    2 answers 2

    Without Redux you can go by passing the value through props . Add a variable to the state of the base component, where we will save the value, and also add a method that will write this value. Pass the value through the props to MainComponent , and transfer the method of writing the value via the props to NavigationBar . We get something like the following code:

     class BaseComponent extends React.Component { constructor(props) { super(props); this.state = { artName: '' }; // переменная, в которой будем хранить значение this.onChangeArtValue = this.onChangeArtValue.bind(this); } onChangeArtValue(value) { this.setState({ artName: value }); } render() { return( <> <NavigationBar onChangeArtValue={this.onChangeArtValue} /> <MainComponent artName={this.state.artName} /> </> ); } } 

    Next, go to the NavigationBar component and use the props method passed through the previously written handleChange method:

     handleChange(e) { this.props.onChangeArtValue(e.target.value); // вызвали метод переданный через пропсу } 

    Now, when the value inside the variable in the NavigationBar component changes, the value in the state of the BaseComponent component will change. When changing, it will be forwarded to the MainComponent component and will cause re-rendering. It remains to make changes to the MainComponent component itself. We need to write a helper method for the Route in order to correctly pass the PS to the component:

     class MainComponent extends React.Component { constructor(props) { super(props); this.renderSearchLine = this.renderSearchLine.bind(this); } renderSearchLine() { // возвращаем SearchLine с переданной пропсой return ( <SearchLine artName={this.props.artName} /> ); } render() { return( <> <Switch> <Route exact path="/all_songs/" component={this.renderSearchLine} /> <Route path="/"> <Redirect to="/all_songs/" /> </Route> </Switch> </> ); } } 

    You can not select a separate method, but I made a separate method for visual understanding. After that, SearchLine will appear inside the SearchLine artName , for this it will be enough to contact props to get its value: this.props.artName . That is, the logic of transfer through propy is quite straightforward and clear.

    If this approach seems too cumbersome, I advise you to pay attention to one very useful thing called Redux .

      You need to use ascend (reverse data flow).

      Here is the structure of the BaseComponent component:

       import React from 'react'; import NavigationBar from '../NavigationBar/NavigationBar'; import MainComponent from '../MainComponent/MainComponent'; class BaseComponent extends React.Component { state = { yourStateName: null, }; lifting = (value) => this.setState({yourStateName: value}); render() { return( <> <NavigationBar lifting={this.lifting.bind(this)} /> <MainComponent yourAttributeName={this.state.yourStateName} /> </> ); } } export default BaseComponent; 

      Here we added the state using the simplified syntax yourNameState: null, created the lifting function, which raises the state of the child component NavigationBar, which we sent to it as the lifting property, and also added the property yourAttributeName to the MainComponent, which will contain the state it needs from NavigationBar, which will now be stored in BaseComponent as a state of yourStateName.

      But already in the NavigationBar component, you need to correctly apply the lifting function to the onChange event handler function of the input element.

      Here is the structure of the NavigationBar component:

       import React from 'react'; import { Link } from 'react-router-dom'; import './NavigationBar.css'; class NavigationBar extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {artName: ''}; } lifting = this.props.lifting; //Michael Pecker: добавляем классу метод lifting, значение берем из this.props handleChange(e) { this.setState({artName: e.target.value}); this.lifting(e.target.value); //Michael Pecker: используем функцию lifting, чтобы отправить состояние родителю } render() { const artistName = this.state.artistName; return( <div className="navBlock"> <img src={require('./search-solid.svg')} width={17} height={17} className="navImage"/> <input placeholder="Type in to Search..." className="input-title" value={artistName} onChange={this.handleChange} /> <div className="navContainer"> <ul> <Link to="/all_songs">All Songs</Link> </ul> </div> <div className="container"> <ul> <Link to="/albums">Albums</Link> </ul> </div> </div> ); } } export default NavigationBar;