如何使用React-Native获取父ListView组件中子复选框组件的状态?

Mic*_*all 9 listview components state parent-child react-native

我有一个选项列表,其中包含复选框和父项内的完成按钮ListView.按下完成按钮后,我想知道选中了哪个复选框.

我应该补充一点,我试图在ListView使用回调函数中维护一个复选框的数组ChildCheckBox.它工作正常,除了导航回来时ListView,阵列将被重置,而复选框似乎仍然被检查.我希望onDonePress()函数只是查询哪些框被检查然后在那时做出相应的响应而不是依赖于ListView维护一个数组.

这是ListView:

class ParentListView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
    };
  }

  componentDidMount() {
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(ROW_DATA),
    });
  }

  onCheckPress() {
    console.log('Check Pressed')
    // callback from ChildCheckBoxCell...?
  }

  onDonePress() {
    console.log('Done pressed')
    // callback from ChildDoneCell...?
  }

  render() {
    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow.bind(this)}
        style={styles.listView}
        />
    );
  }

  renderRow(cell) {
    if (cell.type === 'ChildCheckBoxCell') {
      return (
        <ChildCheckBoxCell onChange={() => this.onCheckPress()} />
      );
    }

    if (cell.type === 'ChildDoneCell') {
      return (
        <ChildDoneCell onDonePress={() => this.onDonePress()}/>
      );
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这是ChildCheckBoxCell组件:

class ChildCheckBoxCell extends Component {

constructor(props) {
    super(props);
    this.state = {
      isChecked: false,
    };
  }

  onChange() {
    this.setState({isChecked: !this.state.isChecked});
    //Callback...
    this.props.onChange();
  }

  render() {
    return (
      <TouchableHighlight onPress={() => this.onChange()}>
        <Text>{this.state.isChecked? 'Checked' : 'UnChecked'}</Text>
      </TouchableHighlight>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,这是ChildDoneCell组件

class ChildDoneCell extends Component {

  onDonePress() {
    //Callback...
    this.props.onDonePress();
  }

  render() {
    return (
      <TouchableHighlight onPress={() => this.onDonePress()}>
        <Text>DONE</Text>
      </TouchableHighlight>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

提前致谢!

rcl*_*lai 4

这是你应该做的。我在代码中添加了注释来解释。应该有6个步骤。

class ParentListView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
    };
  }

  componentDidMount() {
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(ROW_DATA),
    });
  }

  // 1. Change your callback functions to class properties
  // this way it is auto-bound to this class instance and you don't bind it during render, which
  // creates rendering overhead. Notice how the selected `cell` is
  // passed in here. It will be explained in the last steps how that happens.
  onCheckPress = (cell) => {
    // Update the `isChecked` state of this cell and update
    // your `ListView.DataSource` with it
    console.log('Check Pressed', cell);
    // callback from ChildCheckBoxCell...?
  };

  // 2. Do the same thing here as step 1.
  onDonePress = (cell) => {
    console.log('Done pressed', cell);
    // callback from ChildDoneCell...?
  }

  render() {
    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow.bind(this)}
        style={styles.listView}
        />
    );
  }

  renderRow(cell) {
    if (cell.type === 'ChildCheckBoxCell') {
      return (
        // 3. You should pass in the cell data down here AND you should
        // pass a reference to your callback
        <ChildCheckBoxCell cell={cell} onChange={this.onCheckPress} />
      );
    }

    if (cell.type === 'ChildDoneCell') {
      // 4. Do the same thing here, except change the reference of 
      // the callback to the other callback, obviously
      return (
        <ChildDoneCell cell={cell} onDonePress={this.onDonePress}/>
      );
    }
  }
}

class ChildCheckBoxCell extends Component {

  render() {
    return (
      // 5. Dereference the function `onChange` and bind it to your
      // `cell` object, don't worry about `null` changing your 
      // `this` context, it won't. This is how the `cell` object is
      // passed an argument in the method on step 1.
      <TouchableHighlight onPress={this.props.onChange.bind(null, this.props.cell)}>
        {/* Stop using `state` to keep track of `isChecked`, you'll
            lose this state if this ever is torn down and re-rendered
            from the parent component */}
        <Text>{this.props.cell.isChecked? 'Checked' : 'UnChecked'}</Text>
      </TouchableHighlight>
    );
  }
}

class ChildDoneCell extends Component {

  render() {
    return (
      // 6. This is the same thing as step 5.
      <TouchableHighlight onPress={this.props.onDonePress.bind(null, this.props.cell)}>
        <Text>DONE</Text>
      </TouchableHighlight>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

您会注意到,您可以cellrenderRow函数中绑定数据,但这不是首选。要遵循的经验法则是,出于性能原因,您希望尽可能地取消对子数据的回调函数的引用,并且出于维护原因最好是显式的。这是快捷方式的替代方案:

// ParentListView
renderRow(cell) {
  if (cell.type === 'ChildCheckBoxCell') {
    return (
      // No more passing of cell, but now I'm binding it with the
      // cell object
      <ChildCheckBoxCell onChange={this.props.onCheckPress.bind(null, cell)} />
    );
  }

  if (cell.type === 'ChildDoneCell') {
    // Same thing
    return (
      <ChildDoneCell onDonePress={this.onDonePress.bind(null, cell)}/>
    );
  }
}

// ChildCheckBoxCell

render() {
  return (
    // Notice how you lose the explicitness of your callback
    // function and have no idea that this function implicitly passes
    // the `cell` object because you prematurely bound it with the `cell` object
    <TouchableHighlight onPress={this.props.onChange}>
      <Text>{this.props.isChecked? 'Checked' : 'UnChecked'}</Text>
    </TouchableHighlight>
  );
}
Run Code Online (Sandbox Code Playgroud)

编辑

我更新了代码以使其更有意义并消除了不必要的实例方法。在我的第一个示例中,我强烈建议您摆脱 instateChildCheckBoxCell尝试将其props作为对象的一部分来提供cell