ReactJs - 如何从显示嵌套子组件返回到仅显示第一个父组件

时间:2017-05-06 17:54:25

标签: javascript reactjs

  

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中这样做的正确方法是什么?

enter image description here enter image description here

这是我的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>
    );
  }
}

2 个答案:

答案 0 :(得分:1)

这样做的一种方法是让ButtonBackToSearch成为SubmitForm本身的孩子。如您所述 - 它更改了提交表单本身的状态,并且与PresentationResults组件没有真正的连接。在我看来,这是进行这种互动的最干净的“反应”方式。

虽然现实生活可能比这更复杂,但你可能会认为由于其他未提及的原因,按钮必须是嵌套组件的子项。在这种情况下,您可以采取两种方法:

  1. 使用context。在最简单的情况下,只需将SubmitForm实例放在上下文中并公开方法goBack。然后从按钮调用此方法访问提交表单实例并调用此方法。

  2. 使所有组件具有强制属性parent。通过这种方式,您将始终能够“向上”导航层次结构树,并找到您需要的任何父级。之后,与#1相同。这可能听起来有点矫枉过正 - 但它可能会派上用场。

  3. P.S。

    1. 将处理程序传递给SubmitForm中定义的“goBack”函数,直到所有组件。这是#2的一个更加丑陋的变体,我不建议你这样做,因为它会在或多或少的大项目中快速污染你的组件属性。

答案 1 :(得分:1)

我会有三个组件 MainScreen Form Results

MainScreen将管理要向用户显示的屏幕:结果,表单或默认值。

单击时,

BackButton会接受回调。处理程序将为MainScreen本身,并将更改要显示的屏幕的状态。