ReactJs:控制嵌套组件中的流程

时间:2018-08-07 18:31:54

标签: javascript reactjs

我有一个组件A(bigger container),它调用了另外两个组件B(say a kind of header)C (input form)。现在,鉴于用户在C上的行为,我需要隐藏show header。

我有一个解决方案,其中A将功能作为道具传递给C,C可以调用它并更改A中的状态。此修改后的状态传递给B,后者将更改B中的文本。

最小可行示例:-

A:包含带有focused的状态,并调用B和C组件

class A extends React.Component {
  state = {
    focused: true,
  }

  onFocus = () => {
    this.setState({ focused: true });
  }

  onBlur = () => {
    this.setState({ focused: false });
  }
  render() {
    return (
      <div>
        <C onFocus={ this.onFocus } onBlur={ this.onBlur } focus={ this.state.focused } />
        <B focus={ this.state.focused } />
      </div>
    );
  }
}

B:仅根据A的道具显示不同的文本

const B = (props) => (
  props.focus ? <div> Focussed </div> : <div> Blurred </div>
);

C:包含输入文本框,该文本框根据用户操作执行A中的功能

class C extends React.Component {
  state = {
    value: '',
  }

  handleChange(event) {
    this.setState({ value: event.target.value });
  }

  render() {
    return (
      <input type="text"
        value={ this.state.value }
        onChange={ this.handleChange }
        onFocus={ this.props.onFocus }
        onBlur={ this.props.onBlur }
        focus={ this.props.focus }
      />
    );
  }
}

但是,在我的实际应用程序中,我在A和C之间有多个组件(A调用A1调用A2 ...),为了使这些功能可用,所有中间组件都必须将它们作为道具接收。

是否有一种更整洁的方法来解决此要求,而无需让我的每个中间组件都接收这些道具(只希望进一步通过)?

1 个答案:

答案 0 :(得分:1)

我能够举例说明如何使用上下文解决上述问题。在示例A中,在较高级别的组件中设置上下文。

if line:
    lines = line.strip()
    input(f"Does {lines}?>")
    print(eval(lines))

现在,在A之下的任何直接或间接组件都可以读取我们从A传递的值。在我们的情况下,C可以将A的值读取为

const ConveyorBelt = React.createContext();
class A extends React.Component {
  state = {
    focus: true,
    onFocus: () => {
      this.setState({ focus: true });
    },
    onBlur: () => {
      this.setState({ focus: false });
    },
  }

  render() {
    const { focus } = this.state;
    return (
      <div>
        <ConveyorBelt.Provider value={ this.state }>
          <C />
        </ConveyorBelt.Provider>
        <B focus={ focus } />
      </div>
    );
  }
}

现在,我们可以使用A状态更改B中想要的文本。

const C = () => (
  <ConveyorBelt.Consumer>
    { (context) => (
      <input
        onBlur={ context.onBlur }
        onFocus={ context.onFocus }
        autoFocus={ context.focus }
      />
    ) }
  </ConveyorBelt.Consumer>
);

A和C之间可以有尽可能多的组件,并且不需要将道具传递给所有组件。只有C才能读取A传递的数据,从而解决了道具钻孔的问题。