React Native复合组件调用子组件

时间:2018-06-06 05:51:21

标签: reactjs react-native

我有以下反应原生代码。我的想法是,我希望移动所有常用功能(在下面的例子中,它是保存按钮和相应的功能到父类)。

export default class DocumentScreen extends Component {
      save() {
        console.log(this.state);
      }
      render() {
        return (
          <View>
            {this.props.children}
            <View>
              <Button onClick={this.save.bind(this)}/>
            </View>
          <View>
        );
      }
    }

子文档负责实际定义屏幕上显示的字段,例如

export default (props) => (
  <DocumentScreen {...props}>
    <View>
     <TextInput onChangeText={(val) => this.setState({val})}/>
    <View>
  </DocumentScreen>
);

不幸的是,this.setState调用文本输入字段的更改不会改变父对象的状态,所以当我触发save中定义的DocumentScreen函数调用时,它& #39; s状态为空。

我最好的方式是在子组件中公开父{q} setState函数?

谢谢。

3 个答案:

答案 0 :(得分:1)

这是React的常见用例。解决方案应该在父组件内声明处理函数,然后将其传递给子组件。您需要注意函数的上下文,以便this正确指向父函数,可以通过在javascript中使用bind函数或使用箭头函数声明事件处理程序来完成。一个例子如下:

export default class DocumentScreen extends Component {
      changeHandler = (val) => {
        this.setState({ val });
      }

      // Binding function inside JSX should be avoid
      render() {
        return (
          <View>
             {this.props.children}
             <ChildComponent onChange={this.changeHandler} />
          </View>
        )
      }
    }

// Child Component

export default (props) => (
  <DocumentScreen>
    <View>
     <TextInput onChangeText={props.onChange}/>
    </View>
  </DocumentScreen>
);

答案 1 :(得分:1)

因为我看到你使用HOC作为答案,我认为可以使用renderProps。这比使用HOC更好。你获得了更多的自由,而且你也没有道具命名问题。一个好的视频,你可以看到它的强度与HOC https://youtu.be/BcVAq3YFiuc

小例子

class DocumentScreen extends Component {
  state = {
    value: ''
  }

  save() {
    console.log(this.state);
  }

  handleChange = value => {
    this.setState({ value })
  }

  render() {
    return (
      <View>
        {this.props.children({ handleChange: this.handleChange })}
        <View>
          <Button onClick={this.save.bind(this)}/>
        </View>
      </View>
    );
  }
}

const Input = (props) => (
  <DocumentScreen {...props}>
    {({ handleChange }) => (
      <View>
        <TextInput onChangeText={handleChange}/>
      <View>
    )}
  </DocumentScreen>
);

答案 2 :(得分:0)

所以,我最终做的是将我的父组件包装在HOC函数中,如下所示:

export function wrapper(DocumentComponent) {
  return class extends Component {

    changeHandler = (val) => {
      this.setState({ val });
    }

    save() {
      console.log(this.state);
    }

    render() {
      return (
        <View>
          <DocumentComponent onChange={this.changeHanlder}/>
          <View>
            <Button onClick={this.save.bind(this)}/>
          </View>
        <View>
      );
    }

  };    
}

然后我使用包装函数将子句传递给父项(父项现在可以将道具传递回子项)。

export default wrapper(
  (props) => (
    <View>
      <TextInput onChangeText={props.onChange}/>
    </View>
  )
)

虽然在这里发生了一些循环引用......