SubmitForm -parent->结果 - 父母 - >介绍 -parent-> ButtonBackToSearch
我正在尝试学习如何在ReactJs中正确思考并创建单页应用程序。
我正在React中构建Wikipedia Viewer。在我的< SubmitForm />我的用户输入数据的组件,然后在<结果/>组件数据正在准备中。 接下来,它以<演示文稿/>零件。当<演示文稿/>组件处于活动状态我隐藏在css< SubmitForm />搜索窗口。
并且<演示文稿/> component是最后一个组件的父级< ButtonBackToSearch />。该组件有一个按钮,代码如下:
import React from 'react';
export default class ButtonBackToSearch extends React.Component {
constructor(props) {
super(props);
this.state = {isBackToggleOn: false};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({isBackToggleOn: true});
}
render() {
return (
<div>
<button onClick={this.handleClick}>
BACK
</button>
</div>
);
}
}
现在我有一个严肃的谜语。当用户单击BACK按钮并且isBackToggleOn为true时,如何“销毁”所有这些已加载的组件:Results,Presentation,ButtonBackToSearch并返回&lt; SubmitForm /&gt;准备下一次搜索?
我当然可以重新加载页面,但是重新加载所有页面(F5)会像作弊一样,对吧?
在React中这样做的正确方法是什么?
这是我的SubmitForm代码:
import React from 'react';
import axios from 'axios';
import Title from './Title';
import Results from './Results';
export default class SubmitForm extends React.Component {
constructor(props) {
super(props);
this.state = {
data: null,
value: '',
display: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
axiosStart() {
const wikiApiUrl = 'https://en.wikipedia.org/w/api.php?action=opensearch&format=json&origin=*&search=';
const wikiApiUrlWithQuery = wikiApiUrl + this.state.value;
axios.get(wikiApiUrlWithQuery)
.then(response => {
console.log('@axiosStart was launched by user!');
this.setState(Object.assign({}, this.state, { data: response.data }))
})
.catch(err => {
console.log('Error: => ' + err);
this.setState(Object.assign({}, this.state, { data: 'error' }))
});
this.setState({display: 'displayNone'});
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
console.log(('An input was submitted: ' + this.state.value));
// handle change has just updated state
// now app can start axios with entered query
// as soon as user submits
this.axiosStart();
event.preventDefault();
}
render() {
return (
<div className="container">
<div className={this.state.display}>
<form onSubmit={this.handleSubmit}>
<label>
<Title />
<input className="wiki_query" type="text" value={this.state.value} onChange={this.handleChange} autoFocus />
</label>
<button className="btn btn-default" type="submit" value="Submit">Search</button>
</form>
</div>
<Results dataReady={this.state.data} />
</div>
);
}
}
答案 0 :(得分:1)
这样做的一种方法是让ButtonBackToSearch
成为SubmitForm
本身的孩子。如您所述 - 它更改了提交表单本身的状态,并且与Presentation
或Results
组件没有真正的连接。在我看来,这是进行这种互动的最干净的“反应”方式。
虽然现实生活可能比这更复杂,但你可能会认为由于其他未提及的原因,按钮必须是嵌套组件的子项。在这种情况下,您可以采取两种方法:
使用context。在最简单的情况下,只需将SubmitForm实例放在上下文中并公开方法goBack
。然后从按钮调用此方法访问提交表单实例并调用此方法。
使所有组件具有强制属性parent
。通过这种方式,您将始终能够“向上”导航层次结构树,并找到您需要的任何父级。之后,与#1相同。这可能听起来有点矫枉过正 - 但它可能会派上用场。
P.S。
SubmitForm
中定义的“goBack”函数,直到所有组件。这是#2的一个更加丑陋的变体,我不建议你这样做,因为它会在或多或少的大项目中快速污染你的组件属性。答案 1 :(得分:1)
我会有三个组件
MainScreen
Form
Results
MainScreen
将管理要向用户显示的屏幕:结果,表单或默认值。
BackButton
会接受回调。处理程序将为MainScreen
本身,并将更改要显示的屏幕的状态。