#reactjs #parameter-passing #state
#reactjs #передача параметров #состояние
Вопрос:
У меня есть простое приложение для загрузки React / Spring, в котором я хотел бы передать строку поиска на страницу сведений, а затем вернуться к родительской, используя ту же строку поиска в качестве параметра.
В этот момент родительская страница должна принять значение и сохранить его обратно в состоянии.
Что касается существующего кода, когда родительский файл открывается, он устанавливает набор значений в состоянии, включая строку поиска:
constructor(props) {
super(props);
const {cookies} = props;
this.state = {
word: '',
newWord: '',
searchString: '',
licenses: [],
licensePage: [],
csrfToken: cookies.get('XSRF-TOKEN'),
isLoading: true,
licensesPerPage: 7,
activePage: 1,
begin: 0,
end: 7
};
Страница сведений (страница редактирования) вызывается нажатием кнопки на родительской странице:
<Button size="sm" color="primary" tag={Link} to={"/licenses/" license.id}>Edit</Button>
Страница сведений возвращается к родительской, нажав кнопку «Сохранить» или «Отмена»:
<div>
<Button color="primary" type="submit">Save</Button>{' '}
<Button color="secondary" tag={Link} to="/licenses">Cancel</Button>
</div>
Отправка обрабатывается функцией «onSubmit», которая вызывает «handleSubmit:
<Form onSubmit={this.handleSubmit}>
Это handleSubmit — здесь уместна только последняя строка:
async handleSubmit(event) {
event.preventDefault();
if(this.handleValidation()){
} else {
return;
}
const {item, csrfToken} = this.state;
await fetch('/api/license' (item.id ? '/' item.id : '') , {
method: (item.id) ? 'PUT' : 'POST',
headers: {
'X-XSRF-TOKEN': csrfToken,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(item),
credentials: 'include'
});
this.props.history.push('/licenses');
}
Это последняя строка, которую мне нужно изменить:
this.props.history.push('/licenses');
должно быть:
this.props.history.push('/license/search/{searchString}');
Мне просто нужно заполнить строку поиска. Затем я мог бы применить ту же логику к отмене.
Итак, мой вопрос в том, как передать строку поиска дочернему элементу, а затем захватить ее, когда она передается родительскому элементу в URL?
======================= Попытка реализовать сбой ответа на ошибку «не работает» ==========
Я попробовал ответ, но не смог преобразовать его в подход, основанный на классах (я использую классы, а не функции).
Вот код. Обратите внимание, что я временно добавил «2» к именам переменных, чтобы их не путали с существующим кодом.
App.js
import React, { Component } from 'react';
import './App.css';
import Home from './Home';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import LicenseList from './LicenseList';
import LicenseEdit from './LicenseEdit';
import ImportList from './ImportList';
import { CookiesProvider } from 'react-cookie';
class App extends Component {
state = {
searchString2: ""
};
updateSearchString2 = (searchString2) => {
this.setState({
searchString2
});
};
render() {
return (
<CookiesProvider>
<Router>
<Switch>
<Route path='/' exact={true} component={Home}/>
<Route path='/licenses' exact={true} component={LicenseList}
searchString2={this.state.searchString2} // props passed will be same value passed to DetailsPage
updateSearchString2={this.updateSearchString2}
/>
<Route path='/imports' exact={true} component={ImportList}/>
<Route path='/licenses/:id' component={LicenseEdit}/>
</Switch>
</Router>
</CookiesProvider>
)
}
}
export default App;
Соответствующий код в лицензии list.js
<div>
<input type="text" value={this.props.searchString2} onChange={(e) => this.props.updateSearchString2(e.target.value)} />
Это выдает ошибку
TypeError: _this6.props.updateSearchString2 is not a function
Есть мысли?
Комментарии:
1. В вашем вопросе вы спросили «как передать
searchString
дочернему элементу, а затем захватить его, когда он будет передан родительскому элементу». Можете ли вы подтвердить, является ли компонент страницы сведений дочерним по отношению к упомянутому вами компоненту родительской страницы? Можете ли вы также опубликовать свои маршруты?2. Я не уверен, что это дочерний элемент, так как это мое первое приложение React, и я, честно говоря, просто пробиваюсь через это. Я добавил код в вопрос. Обратите внимание, что моя стратегия изменилась с использования исходного идентификатора «/ licenses» в маршруте на «/license/{searchString}». Идея заключается в том, что если searchString имеет значение null, API вернет все лицензии (как это делает оригинал «/licenses»), но если строка содержит что-то, она вернет только соответствующие лицензии.
Ответ №1:
У вас может быть 1 источник достоверности для searchString
состояния, так что это состояние будет передано как prop как компоненту «ParentPage», так и компоненту «DetailsPage». Для этого у вас может быть общий родительский компонент как для ParentPage, так и для компонента DetailsPage
export default class App extends React.Component {
state = {
searchString: ""
};
updateSearchString = (searchString) => {
this.setState({
searchString
});
};
render() {
return (
<div className="App">
<Route
exact
path="/"
render={() => (
<ParentPage
searchString={this.state.searchString} // props passed will be same value passed to DetailsPage
updateSearchString={this.updateSearchString}
/>
)}
/>
<Route
path="/license"
render={() => <DetailsPage searchString={this.state.searchString} />}
/>
</div>
);
}
}
В этом сценарии, независимо от какой-либо маршрутизации, которая произошла, или каких-либо изменений состояния, searchString
значение останется неизменным во всех ваших компонентах
Для этого требования:
Идея заключается в том, что если searchString имеет значение null, API вернет все лицензии (как это делает «/licenses»), но если строка содержит что-то, она вернет только соответствующие лицензии.
поскольку у вас уже есть доступ к searchString
, на этом этапе вы можете использовать операторы условий на основе searchString
значения и оценить, нужен ли вам API для возврата всех лицензий или нет и т. Д
Комментарии:
1. У меня возникли проблемы с преобразованием этого в реализацию на основе классов — я получаю «updateSearchString», это не функция. Если вы хотите взглянуть, я опубликовал код в теле.
2. вы можете использовать
render
prop вместоcomponent
prop для вашего<Route/>
. внутриrender
функции обратного вызова вы помещаете свой JSX вместе с реквизитами. Пример:render={() => ( <LicenseList searchString2={this.state.searchString2} updateSearchString2={this.updateSearchString2} /> )}
3. Спасибо — это работает! Итак, просто изменив «Component» на «render», это позволяет передавать функцию? Учитывая это, есть ли какая-либо причина когда-либо использовать Component в команде route? Может быть, потому, что это легче читать… Мне действительно нужно собрать все воедино и понять различия между программированием на основе классов и функциональным программированием в React. С фоном в Java, очевидно, классы проще и интуитивно понятнее, но функциональное программирование похоже на то, что такое React, по крайней мере, на основе примеров, которые я вижу.
4. Технически
component
можно использовать таким же образом. Основное отличие заключается в том, что, как объясняется в документации , использованиеcomponent
создаст новые элементы React для рендеринга, это означает, что старый размонтируется и отображается совершенно новый элемент React. Продолжайте и протестируйте его в моем CodeSandbox. Просто заменитеrender
prop наcomponent
prop. Вы заметите, что ввод в поле ввода (т. Е. Обновление состояния) приведет к монтированию нового элемента — поэтому первоначальный ввод больше не находится в DOM, поэтомуfocus
теряется.