我该如何构造这个React Native Section List实现

时间:2019-04-02 17:42:31

标签: reactjs react-native react-native-flatlist react-native-sectionlist

所以我想以一种非正统的方式使用RN Section列表。

我希望部分列表将渲染传递给组件,因为渲染不会很统一。

我想使用部分列表,以便在滚动时仍然可以看到标题。

我制作了一个可以吸收子项并将其呈现在部分列表中的组件,如下所示:

class SomeSectionList extends Component {

    render() {
        let sections = React.Children.map(this.props.children, (Child, index) => {
            return {title: Child.type.title, data: [''], renderItem: () => Child, index }
    });

        return (
            <SectionList

                renderSectionHeader={({section}) => {
                    return <Text style={{ fontWeight: "bold" }}>{section.title}</Text>
        }}
                sections={sections}
                keyExtractor={(item, index) => item + index}
            />
        );
    }
}

用法如下:

                <SomeSectionList>
                    <Comp1 />
                    <Comp2 />
                </SomeSectionList>

但是,我的问题是。说在这种情况下,Comp1不会从其组件中呈现任何内容,我希望能够从部分列表中隐藏其部分。

SomeSectionList组件如何知道它没有呈现任何内容或没有数据可以呈现任何内容,因此可以隐藏其部分和标题?

任何建议都会很棒。我觉得使用SectionList这样做是过分的(但它使标头显示得更好),因此也对替代品开放。

2 个答案:

答案 0 :(得分:4)

您可以使用onLayout随附的View方法来完成此操作。

通过它我们可以获取渲染的组件的高度。如果为0,则表示其中未呈现任何内容,否则包含某些数据。

查看此Working example on snack

export default class App extends React.Component {
  render() {
    return (
      <SomeSectionList>
        <Comp1 />
        <Comp2 />
        <Comp1 />
        <Comp2 />
        <Comp1 />
      </SomeSectionList>
    );
  }
}

class Comp1 extends React.Component {
  render() {
    return (
      <View>
        <Text>Comp11</Text>
      </View>
    );
  }
}

class Comp2 extends React.Component {
  render() {
    return null;
  }
}

class SomeSectionList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      children: this.props.children,
    };
  }
  onLayout = (event, index) => {
    if (event.nativeEvent.layout.height <= 0) {
      let oldProps = this.state.children;
      oldProps.splice(index, 1);
      this.setState({ children: oldProps });
    }
  };
  render() {
    let sections = React.Children.map(this.state.children, (Child, index) => {
      return {
        title: Child.type.title,
        data: [''],
        renderItem: () => (
          <View onLayout={event => this.onLayout(event, index)}>
            {this.state.children[index]}
          </View>
        ),
        index,
      };
    });

    return (
      <SectionList
        renderSectionHeader={({ section }) => {
          return <Text style={{ fontWeight: 'bold' }}>{section.title}</Text>;
        }}
        sections={sections}
        keyExtractor={(item, index) => item + index}
      />
    );
  }
}

在这里,首先,我们将this.props.children分配到状态。然后在onLayout方法中,我们检查当前索引的子级是否具有0高度。如果是,则将其从子级数组中删除。

您将清楚地看到某些视图正在删除。为此,我们在一种情况下所做的事情是放置一个装载器,该装载器以绝对位置覆盖整个SectionList区域,您可以在正确渲染所有东西时将其隐藏。

答案 1 :(得分:0)

以下是我在考虑@JaydeepGalani的有用建议后的另一种选择!

class SomeSectionList extends Component {
  constructor(props) {
    super(props)
    this.state = {
            hiddenChildren: {}
    }
  }


  onLayout = (event, index) => {
    if (event.nativeEvent.layout.height <= 0) {
            const hiddenChildren = this.state.hiddenChildren
            hiddenChildren[index] = true
            this.setState({
                hiddenChildren
            })
    } else {

            const hiddenChildren = this.state.hiddenChildren
            delete hiddenChildren[index]
            this.setState({
                hiddenChildren
            })
    }
  }

    render() {
        let sections = React.Children.map(this.props.children, (Child, index) => {
            return {
                title: Child.type.title, 
                index,
        data: [''], 
        renderItem: () => (
          <View onLayout={event => this.onLayout(event, index)}>
            {this.state.children[index]}
          </View>
      )}
    });

        return (
            <SectionList

                renderSectionHeader={({section}) => {
                    const index = section.index
                    if (this.state.hiddenChildren[index]) return 

                    return <Text style={{ fontWeight: "bold" }}>{section.title}</Text>
        }}
                sections={sections}
                keyExtractor={(item, index) => item + index}
            />
        );
    }
}

因为在第一个实现中,一旦删除了该部分,由于onLayouts不会被触发,因此很难将其恢复。在这种情况下,我们仍然在技术上“渲染”该部分,但是隐藏了标题,并且由于该部分的高度为0,因此它不会显示,但是它仍然被渲染,并在以后的某个时间点说该部分发生了变化并突然对其进行了渲染现在将显示在部分列表中。

是否对此有任何反馈?