【问题标题】:Defining React Prop Keys When Calling Static Child Components调用静态子组件时定义 React Prop 键
【发布时间】:2019-01-13 16:01:32
【问题描述】:

我试图更好地理解键在 React 组件中的作用。我读了很多,但我看到的每个示例(例如React docsthe great explanation on S.O. 中的示例)都假设进入组件的数据是动态的。

这些示例都应用了带有数组索引值的键或使用类似.map() 的东西来动态地将数据库 ID 分配给子组件的每个实例,并满足 React 对键的需求。

我的示例是在一个静态网站上,其中静态内容进入子组件并被调用了几次。最好的我想,我可以创建一个随机数生成器函数getRandomInt 并以这种方式应用密钥。

不幸的是,这导致了熟悉的 React 错误:

数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。 检查CaseStudyOpinionSummary的渲染方法。它通过了 来自DiagnosticCaseStudy的孩子。

我哪里错了?

父组件 (DiagnosticCaseStudy)

import React from 'react'
import CaseStudyOpinionSummary from '../../../components/CaseStudyOpinionSummary'

export default class DiagnosticCaseStudy extends React.Component {

  getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min
  }

  render() {
    return (
      <CaseStudyOpinionSummary
        part="Part One"
        partTitle="Diagnosis"
        partSubtitle="Primary Care Encounter"
        partSummary="Short brief"
        key={ this.getRandomInt(0, 100000) } 
      />
      <CaseStudyOpinionSummary
        part="Part Two"
        partTitle="Medication and Management"
        partSubtitle="Initial Gastroenterologist Encounter"
        partSummary="Another short brief"
        key={ this.getRandomInt(0, 100000) } 
      />
    )
  }

子组件 (CaseStudyOpinionSummary)

import React from 'react'

export default class CaseStudyOpinionSummary extends React.Component {

  render() {
    return (   
      <div> 
        <section className="lightest-gray-bg">
          <section className="aga-cs-container-short">
            <section className="aga-container">
              <h2 className="aga-cs-orange-title">{[this.props.part, ": ", this.props.partTitle ]}</h2>
              <h2 className="aga-cs-question-title">{ this.props.partSubtitle }</h2>
              { this.props.partSummary }
            </section>
          </section>
        </section>
      </div>
    )
  }
}

【问题讨论】:

  • 您只需要在渲染 React 元素数组时使用键(例如,map 的结果是一个数组,就像您提到的那样)。否则你不需要钥匙。如果您在每次渲染时随机一个键,这意味着该组件将被卸载并在每次渲染时安装一个新的(!),这不是您想要的。在DiagnosticCaseStudy 的情况下,您可以将组件包装在div 中,或者例如如果你想返回一个数组,给他们每个键 12
  • 渲染这个{[this.props.part, ": ", this.props.partTitle ]}的目的是什么?你只是想连接字符串吗?如果是这样,请尝试将它们真正连接起来,然后渲染该字符串,而不是渲染数组。 {this.props.part + ": " + this.props.partTitle}
  • 您的父组件必须只返回一个元素。将两个子组件包装在 divReact.Fragment 中。
  • @Tholle 只是补充一点:当上下文发生变化时,键也可以用于“重置”组件。虽然这与这个特定问题无关。
  • @trixn 是的,你是对的,因此在我的评论中“这意味着组件将被卸载并在每次渲染时安装一个新组件(!)”。

标签: javascript reactjs random


【解决方案1】:

React 只需要 key 属性来区分数组中的兄弟组件。对于常规兄弟组件,您不需要 key 属性。

class AppWithArray extends React.Component {
  render() {
    return (
      <div>
      {[
        <div key="1"> test1 </div>,
        <div key="2"> test2 </div>
      ]}
      </div>
    );
  }
}

class AppWithoutArray extends React.Component {
  render() {
    return (
      <div>
        <div> test3 </div>
        <div> test4 </div>
      </div>
    );
  }
}

ReactDOM.render(
  <div>
    <AppWithArray />
    <AppWithoutArray />
  </div>,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

当一个组件获得一个新的key 属性时,旧的将被卸载并丢弃,新的将被创建和安装。您几乎从不在数组之外使用 key 属性,但如果您需要创建一个全新的组件,请牢记这一技巧。

class Timer extends React.Component {
  timer = null;
  state = { count: 0 };

  componentDidMount() {
    this.timer = setInterval(() => {
      this.setState(prevState => ({ count: prevState.count + 1 }));
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }

  render() {
    return <div>{this.state.count}</div>;
  }
}

class App extends React.Component {
  state = { timerKey: 1 };

  componentDidMount() {
    setTimeout(() => {
      this.setState({ timerKey: 2 });
    }, 5000);
  }

  render() {
    return <Timer key={this.state.timerKey} />;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

【讨论】:

  • 感谢第二个示例,我没有考虑过有趣的用例。
猜你喜欢
  • 1970-01-01
  • 2021-10-15
  • 2018-09-14
  • 1970-01-01
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多