使用setNativeProps设置后访问属性值

时间:2018-04-19 11:48:56

标签: react-native

我正在尝试在React Native(使用Coffeescript)中切换动态创建的组件的显示。创建的组件符合JSON对象的结构,并且每个组件都具有ref属性,具有相应的id,因此我可以访问特定组件,如下所示:this.refs[ id ]

我有以下功能来更改组件的显示

changeDisplay: ( id ) ->
  this.refs[ id ].setNativeProps( {
    display: 'flex'
  } );

当我想要更改初始显示时,此功能正常,但我想在noneflex之间切换显示(基于当前状态)。

因为我不知道在正手上呈现了多少项目,所以我不能(或不知道如何)为它们定义状态。

我尝试了以下操作,但在使用setNativeProps()

设置后,我无法以新的显示状态返回
changeDisplay: ( id ) ->
  if this.refs[ id ].props.style.display is 'none'
    this.refs[ id ].setNativeProps( {
      display: 'flex'
    } );
  else
    this.refs[ id ].setNativeProps( {
      display: 'none'
    } );

最初this.refs[ id ].props.style.display返回组件在加载视图时所处的状态(= none),但是在我运行上面的函数之后,显示状态在视觉上被更改(组件显示),但this.refs[ id ].props.style.display仍会返回初始状态none

为什么呢?

修改

下面是我的(剥离的)组件(根据要求)。我想切换某个项目中子任务的显示。因此,如果我点击项目Project 1,我想切换任务的显示状态1& 2。

import React from 'react';

import {
  StyleSheet,
  Text,
  View,
  TextInput,
  TouchableOpacity,
  ScrollView
} from 'react-native';

import {
  Icon,
} from 'react-native-elements';

class ListTasks extends React.Component

  constructor: ( props ) ->
    super props

    this.data =
      list: [
        {
          id: 1
          name: 'Project 1'
          type: 'project'
          parent: null
        },{
          id: 2
          parent: 1
          name: 'Task 1'
          type: 'task'
        },{
          id: 3
          parent: 1
          name: 'Task 2'
          type: 'task'
        },{
          id: 4
          name: 'Project 2'
          type: 'project'
          parent: null
        },{
          id: 5
          parent: 4
          name: 'Task 3'
          type: 'task'
        },{
          id: 6
          parent: 4
          name: 'Task 4'
          type: 'task'
        }
      ]

  toggleDisplay: ( id ) ->
    if this.refs[ id ].props.style.display is v[ 0 ]
      this.refs[ id ].setNativeProps( {
        display: 'flex'
      } );
    else
      this.refs[ id ].setNativeProps( {
        display: 'none'
      } );

  renderList: ( data ) ->
    <View>
      <View>
        <TouchableOpacity onPress={() => this.toggleDisplay( data.id )}>
          <Text>{data.name}</Text>
        </TouchableOpacity>
      </View>

      <View ref={data.id} style={display: 'none'}>
        { this.renderTask cor for cor in this.data.list when cor.parent is data.id }
      </View>
    </View>

  renderTask: ( data ) ->
    <View>
      <Text>{data.name}</Text>
    </View>

  render: ->
    <View>
      <ScrollView style={height:'100%'}>
        { this.data.list.map( ( data ) =>
          if data.type == 'project'
            this.renderList( data )
        ) }
      </ScrollView>
    </View>

export default ListTasks

1 个答案:

答案 0 :(得分:0)

您的数据结构不是非常适合存储明显具有2D截面关系的数据。我在下面修改了数据结构。

DOM操作也不是React方式。相反,我们使用状态来管理元素的可见性和属性。

分段可折叠列表的工作示例:

import React from 'react';
import { Text, TouchableOpacity, SectionList } from 'react-native';

const data = [
  {
    id: 1,
    name: 'Project 1',
    type: 'project',
    data: [
      {
        id: 2,
        name: 'Task 1',
        type: 'task',
      },
      {
        id: 3,
        name: 'Task 2',
        type: 'task',
      },
    ],
  },
  {
    id: 4,
    name: 'Project 2',
    type: 'project',
    data: [
      {
        id: 5,
        name: 'Task 3',
        type: 'task',
      },
      {
        id: 6,
        name: 'Task 4',
        type: 'task',
      },
    ],
  },
];

class ListTasks extends React.Component {
  state = {
    list: data,
    show: {},
  };

  render() {
    // SectionList is used instead of ScrollView as it has better performance
    return (
      <SectionList
        style={{ marginTop: 50 }}
        sections={this.state.list}
        renderItem={({ item, section }) =>
          // render null if show state for the section is falsy
          (this.state.show[section.id] ? <Text style={{ padding: 10 }}>{item.name}</Text> : null)
        }
        renderSectionHeader={({ section }) => (
          <TouchableOpacity
            style={{ paddingVertical: 10, margin: 10, backgroundColor: 'grey' }}
            onPress={() =>
              this.setState((prevState) => ({
                show: {
                  ...prevState.show,
                  // toggle the show state for the seciton
                  [section.id]: !prevState.show[section.id],
                },
              }))
            }
          >
            <Text>{section.name}</Text>
          </TouchableOpacity>
        )}
        keyExtractor={(item) => item.id}
      />
    );
  }
}

export default ListTasks;