React Native - 根据'key'引导错误将子组件放入父组件中

时间:2018-01-11 02:16:02

标签: reactjs react-native react-navigation

我在这里创建一个已安装react-navigation的本机反应项目 我已经为应用程序中的页面打开了StackNavigator。以下是我要存档的内容。

我想在不使用提供的标头的情况下使用StackNavigator。因此,我创建了一个组件<Header>,如下所示:

export default class Header extends Component {
  constructor(props) {
    super(props);
  }

  detectKeyAndRender(item) {
    if (item.key === "left") {
      return <View style={leftContainerStyle}>{item}</View>;
    } else if (item.key === "middle") {
      return <View style={middleContainerStyle}>{item}</View>;
    } else if (item.key === "right") {
      return <View style={rightContainerStyle}>{item}</View>;
    }
  }

  render() {
    return (
      <View key="header" style={headerContainerStyle}>
        { this.props.children.map((item) => ( this.detectKeyAndRender(item) )) }
      </View>
    );
  }
}

对于常见的样式和容器结构,我创建了一个名为<BaseContainer>的组件,如下所示:

import { getChildComponent } from 'helper.js';

export default class BaseContainer extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <SafeAreaView key="safe-area-view" style={safeAreaViewStyle}>

        { /* Please set the header from each page */ }
        { getChildComponent(this.props.children, "header") }

        <View style={outerContainerStyle}>
          <ScrollView contentContainerStyle={scrollViewStyle} alwaysBounceVertical={false}>

            { /* Page content goes in here */ }
            { getChildComponent(this.props.children, "content") }

          </ScrollView>
        </View>

      </SafeAreaView>
    );
  }
}

还有helper.js

export function getChildComponent(children, key) {
  return children.filter( (comp) => {
    return comp.key === key;
  });
}

因此在其他页面中,我可以像下面这样调用标题:

export default class FirstPage extends Component {
  render() {
    <BaseContainer>
      <Header key="header">
        <Text key="left">Left</Text>
        <Text style={{color: '#fff', fontSize: 20}} key="middle">First Page</Text>
        <Text key="right">Right</Text>
      </Header>
      <View key="content">
        <Text>This is first page.</Text>
      </View>
    </BaseContainer>
  }
}

export default class SecondPage extends Component {
  render() {
    <BaseContainer>
      <Header key="header">
        <Text key="left">Left</Text>
        <Text style={{color: '#fff', fontSize: 20}} key="middle">Second Page</Text>
        <Text key="right">Right</Text>
      </Header>
      <View key="content">
        <Text>This is second page.</Text>
      </View>
    </BaseContainer>
  }
}

<Header>的这种渲染方法会带来错误但不是致命的。错误与唯一键有关:

Warning: Each child in an array or iterator should have a unique "key" props.
Check the render method of `Header`.

我知道内部反应原生,每个键应该是唯一的(针对性能问题)。

因此我想问一下是否有更好的方法将特定的子组件放入标题中,或者根据“键”添加样式?感谢任何帮助。

请尽量使解决方案尽可能简单。将一些常见代码组合在一起就是我想归档的内容。

注意:我不想在react-navigation中使用自定义标头,因为它放置的位置不是我想要的。

2 个答案:

答案 0 :(得分:0)

摆脱错误的一种简单方法是通过向key添加第二个参数,为View生成的detectKeyAndRender组件添加唯一detectKeyAndRender(item, key)。所以你的功能就是例如View

在函数内部,只需将该关键参数添加到每个返回的<View key={key} ... />{ this.props.children.map((item, i) => ( this.detectKeyAndRender(item, i) )) }

然后,当您实际映射子项时,将索引传递给函数:

= true,

答案 1 :(得分:0)

应为每个子元素指定唯一键。

标题

export default class Header extends Component {
 constructor(props) {
    super(props);
 }

 detectKeyAndRender(item) {
  /* you can use 'left,'middle' & 'right' as keys - they are different */
  let { key } = item;

  /* do validation on style hence you are not changing anything on view */
  /* 'Conditional Operator' is used to simplify if...else...if...else */
  let style =
    key === "left"
      ? leftContainerStyle
      : key === "middle"
        ? middleContainerStyle
        : key === "right"
          ? rightContainerStyle
          : middleContainerStyle /* default */;

  return (
    <View key={key} style={style}>
      {item}
    </View>
   );
  }

 render() {
  return (
    <View key="header" style={headerContainerStyle}>
      {this.props.children.map(item => this.detectKeyAndRender(item))}
    </View>
  );
 }
}