以编程方式反应附加组件

时间:2018-09-25 18:40:41

标签: javascript reactjs

我想创建一个react组件实例,并以编程方式将其渲染到静态位置。 我的用例是,我以未知的长度打开一系列对话框,当收到对话框的响应时,我打开下一个。

我想做类似的事情:

const DialogExample = () => ({ question, onAnswer }) =>
  (<div>
    {question}
    <button onClick={onAnswer}>answer</button>
  </div>);

class SomeComponent extends React.Component {
  async start() {
    const questions = await getSomeDynamicQuestions();
    this.ask(questions);
  }

  ask(questions) {
    if (questions.length === 0) {
      // DONE.. (do something here)
      return;
    }

    const current = questions.pop();

    React.magicMethod(
        // The component I want to append:
        <DialogExample 
            question={current} 
            onAnswer={() => this.ask(questions)}
        />,
        // Where I want to append it:
        document.getElementsByTagName('body')[0]);
  }

  render() {
    return (
      <div>
        <button onClick={this.start}>start</button>
      </div>);
  }
}

我知道那不是很“像反应”,而且我想这样做的“正确”方法是将这些问题存储在状态中,并在“ someComponent”(或其他)渲染函数中对其进行迭代,但是,我认为这种模式在我的特定需求中很有意义。

1 个答案:

答案 0 :(得分:2)

听起来像Portals的情况。我建议做这样的事情:

class SomeComponent extends React.Component {
  constructor(props) {
    super(props);
    this.body = document.getElementsByTagName('body')[0];
    this.state = {
      questions: [],
    }
  }

  async start() {
    const questions = await getSomeDynamicQuestions();
    this.setState({ questions });
  }

  nextQuestion() {
    this.setState(oldState => {
      const [first, ...rest] = oldState.questions;
      return { questions: rest };
    })
  }

  render() {
    const { questions } = this.state;
    return (
      <div>
        <button onClick={this.start}>start</button>
        {questions.length > 0 && ReactDOM.createPortal(
          <DialogExample
            question={questions[0]}
            onAnswer={() => this.nextQuestion()}
          />,
          this.body,
        )}
      </div>
    );
  }
}
相关问题