Есть две компоненты одного уровня, мне нужно передать значение которое было получено в компоненте NavigationBar в компоненту SearchLine
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;
компонента SearchLine содержится в 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;
вот компонента NavigationBar
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;
Я не понимаю как мне правильно взять из NavigationBar значение, которое было введено в input, и передать его в SearchLine?
Без Redux можно пойти путем передачи значения через props. Добавить в стейт базового компонента переменную, куда будем сохранять значение, а также добавить метод, который будет записывать это значение. Передадим значение через пропсу в MainComponent, а метод записи значения передадим через пропсу в NavigationBar. Получим что-то вроде следующего кода:
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} />
</>
);
}
}
Далее перейдем в компонента NavigationBar и испольуем переданный через props метод внутри ранее написанного handleChange метода:
handleChange(e) {
this.props.onChangeArtValue(e.target.value); // вызвали метод переданный через пропсу
}
Теперь при изменении значения внутри инпута в NavigationBar компоненте, будет меняться значение в стейте BaseComponent компонента. Оно же при изменении будет пробрасываться в MainComponent компонент и вызывать ререндеринг. Осталось внести правки в сам MainComponent компонент. Нам нужно написать вспомогательный метод для Route, чтобы правильно передать пропсу в компонент:
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>
</>
);
}
}
Можно не выделять отдельный метод, но я сделал для наглядного понимания отдельный метод. После этого, внутри компонента SearchLine появится пропса artName, для этого будет достаточно обратиться в пропсы, для получения ее значения: this.props.artName. То есть, логика передачи через пропсы достаточно прямолинейна и ясна.
Если данный подход покажется слишком громоздким, то советую обратить внимание на одну очень полезную штуковину под названием Redux.
Тебе необходимо использовать подъем состояния (обратный поток данных).
Вот структура компонента BaseComponent:
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;
Здесь мы добавили состояние через упрощенный синтаксис yourNameState: null, создали функцию lifting, поднимающую состояние дочернего компонента NavigationBar, которую мы отправили ему же как свойство lifting, а также, добавили в MainComponent свойство yourAttributeName, в котором и будет содержаться необходимое ему состояние из NavigationBar, которое теперь уже будет храниться в BaseComponent в качестве state yourStateName.
А вот уже в компоненте NavigationBar нужно правильно применить функцию lifting в функцию-обработчик события onChange элемента input.
Вот структура компонента NavigationBar:
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;
Продвижение своими сайтами как стратегия роста и независимости