将本机ref对呈现的类进行反应

时间:2018-10-19 01:06:55

标签: class react-native render ref

我正在尝试创建一个简单的应用程序:按一个按钮并将一个项目添加到列表中。

这是一种尝试:

export default class App extends Component<Props> {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  } 

  onPressButton = () => {
    this.myRef.setState({data: [this.myRef.state.data, {key: 'test'} ]});
  }


  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>Welcome to React Native!</Text>
        <MsgList  ref={(comp) => {this.myRef = comp;}}/>
        <TouchableOpacity onPress={this.onPressButton}>
          <Text>press</Text>
        </TouchableOpacity> 
      </View>
    );
  }
}

MsgList

class MsgList extends Component {

  render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={[
            {key: 'Devin'},
            {key: 'Jackson'},
            {key: 'James'},
          ]}
          renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>}
        />
      </View>
    );
  }
}      

this.Ref是一个大的圆形结构,但不是节点,因此 ref error

我尝试了ReactDOM.findDOMNode但收到错误 从'react-dom'导入ReactDOM import error

我尝试了许多迭代。我最好的猜测是有一种更好的方式呈现MsgList。

2 个答案:

答案 0 :(得分:0)

推荐解决方案

在父组件中使用state来处理子props,而不使用ref

App.js

export default class App extends Component<Props> {
  constructor(props) {
    super(props);
  } 

  onPressButton = () => {
    this.setState((prevState, props) => ({ // Use setState for changing 
      data: prevState.data.concat({key: 'test'}),
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <MsgList  data={this.state.data} />
        <TouchableOpacity onPress={this.onPressButton}>
          <Text>press</Text>
        </TouchableOpacity> 
      </View>
    );
  }
}

另一种解决方案

setNativeProps可能是您想要的方式。

App.js

onPressButton = () => {
  this.myRef.setNativeProps({ // Change ref's props directly
    data: {key: 'test'}
  });
},

MsgList类

class MsgList extends Component {
  render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={this.props.data} // Get data from props. 
          renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>}
        />
      </View>
    );
  }
}    

但这可能是性能瓶颈。

  

在频繁重新渲染会产生性能瓶颈时使用setNativeProps

     

直接操作将不是您经常使用的工具;您通常只会将其用于创建连续动画,以避免呈现组件层次结构和协调许多视图的开销。 setNativeProps是命令性的,它将状态存储在本机层(DOM,UIView等)中,而不是存储在React组件中,这使您的代码更难以推理。在使用它之前,请尝试使用setState和shouldComponentUpdate解决问题。

Official

为什么?

state应该由组件self管理。这就是您之前尝试过this.ref.state为null的原因。因此,如果值是动态的,则可以通过setState将道具从父项传递给子项。 并且state更新可能是异步的。这就是为什么我在prevState中使用setState的原因。 Doc

答案 1 :(得分:0)

基于输入I lifted the state up

export default class App extends Component<Props> {
    constructor(props) {
        super(props);

         this.state = {
            data: [{key: 'Devin'},
            {key: 'Jackson'},
            {key: 'James'},]
         }
    }


    onPressButton = () => {
        this.setState({data: this.state.data.concat( {key: 'test'} )});
    }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>Welcome to React Native!</Text>
        <MsgList data={this.state.data}  />
            <TouchableOpacity onPress={this.onPressButton}>
                <Text>press</Text>
            </TouchableOpacity> 
      </View>
    );
  }
}

 class MsgList extends Component {

  render() {
    return (
      <View style={styles.container}>
        <FlatList
            data={this.props.data}
            renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>}
        />
      </View>
    );
  }
}