Я создаю реагирующее одностраничное приложение, которое будет вызывать API для поиска на основе ввода пользователя, и пользователь должен войти в систему, чтобы иметь возможность использовать приложение.
Иерархия компонентов:
App.js
(обрабатывает вход в систему и маршрутизацию) <SearchPage />
и <SearchResults />
- Есть
<SearchNavBar />
и <SearchMain />
под <SearchPage />
(<SearchMain />
содержит форму и данные для отправки пользователями, и после отправки пользователи должны перейти к маршруту, по которому находится <SearchResults />
.)
Вот проблема: поскольку реакция разрешает поток данных только в одном направлении, я должен передать ввод пользователя от <SearchMain />
вверх до App.js
, а затем сохранить его в состоянии App.js
и передать его вниз как опора до <SearchResults />
вместе с токеном, полученным от App.js
. Однако даже я обновил состояние в App. js и передал его как опору его дочернему компоненту <SearchResults />
, в то время как console.logging реквизиты дочернего компонента <SearchResults />
, я мог получить только начальные значения состояния, а не обновленные, почему ??
Код:
Приложение. js:
const myMSALObj = new UserAgentApplication(msalConfig);
class App extends Component {
constructor(props) {
super(props)
this.state = {
res:'',
isLoggedIn:false,
keyword:''
}
this.handleLogOut = this.handleLogOut.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleLogOut(){
myMSALObj.logout();
this.setState({isLoggedIn:false})
}
handleSubmit (typedValue){
this.setState({keyword:typedValue},() => console.log(this.state));//here works just fine, showing correct state value
window.location.replace('/results')
};
async componentDidMount(){
const idToken_response = await myMSALObj.loginPopup(loginRequest);
const response = await myMSALObj.acquireTokenPopup(loginRequest);
this.setState({isLoggedIn:true,res:response});
}
render(){
return (
<Router>
<div>
<Switch>
{this.state.isLoggedIn === true ?
<Route exact path="/" render={() => <SearchPage
parentState = {this.state}
handleLogOut = {this.handleLogOut}
handleSubmit = {this.handleSubmit} />}/>:
<Route exact path="/" render={() => (<div>Please wait till you are logged in...</div>)}/>}
<Route exact path="/results" render={() => <SearchResults
parentState = {this.state.keyword}
handleLogOut = {this.handleLogOut} />}/>
</Switch>
</div>
</Router>
);
}
}
export default App;
SearchPage:
class SeachPage extends Component{
constructor (props){
super (props);
this.state = {
// userInfo: this.props,
accessToken: this.props.parentState.res.accessToken,
name:this.props.parentState.res.account.name,
email:this.props.parentState.res.account.userName
}
// console.log(this.props)
}
render(){
return (
<Fragment>
<SearchNavBar
info={this.state}
handleLogOut = {this.props.handleLogOut}/>
<SearchMain
accessToken={this.state.accessToken }
handleSubmit = {this.props.handleSubmit}/>
</Fragment>
)
}
}
export default SeachPage;
SearchMain:
class SearchMain extends Component{
constructor(props){
super(props);
this.state = {
token:this.props.accessToken,
keyword:'',
typed:'',
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmitForm = this.handleSubmitForm.bind(this);
// console.log(this.props)
}
handleChange(event) {
let typed = event.target.value;
let keyword = event.target.value;
this.setState({typed: typed,keyword:keyword},() => console.log(this.state));
};
handleSubmitForm(event){
const keyword = this.state.keyword;
this.props.handleSubmit(keyword);
event.preventDefault();
}
render(){
return(
<div className="container" id="searchBox">
<form onSubmit = {this.handleSubmitForm } className="field is-grouped">
<p className="control is-expanded">
<input type="text" className="input" value={this.state.keyword} onChange={this.handleChange} autoComplete="off" placeholder="Find an asset" required></input>
</p>
<p className="control">
<button id="button-in-nav-bar" type="submit" className="button is-primary"><strong>Search</strong></button>
</p>
</form>
</div>
)
}
};
export default SearchMain;
SearchResults
class SearchResults extends Component {
constructor(props){
super(props);
console.log(this.props) //here is the issue!! onlyshowing{res:'',isLoggedIn:false,keyword:''}
}
render (){
return(
<div>test results</div>
)
}
};
export default SearchResults;
Update Итак, вкратце, я смог передать ключевое слово вверх родительскому компоненту, кажется, немного поздно, скриншоты могут лучше описать мою борьбу: и если я раскомментирую window.location.replace('/results')
на первом снимке экрана, страница будет перемещена на '/results'
, и если I console.log(this.props)
в функции рендеринга , реквизиты отображались 4 раза, а последние 2 раза имели частично правильную информацию. , все же ключевое слово отсутствовало ... У меня было ощущение, что это может быть b c асинхронной c природы, но я действительно ничего не знаю о h как это исправить .. (побочный вопрос, почему он 4 раза проиграл?)