在 react-native 中调用其他组件的函数

Calling functions from other components in react-native

如何在 react-native 中调用其他组件的函数?

我有这个自定义组件,它呈现在其他地方定义的另一个组件和一个图像按钮。点击图像时,我想从其他组件调用一个函数。执行下面的示例时,我得到 undefined is not an object (evaluating this.otherComponent.doSomething')

export default class MainComponent extends Component {

  _onPressButton() {
    this.otherComponent.doSomething();
  }

  render() {
    return (
      <View style={styles.container}>
        <TagContainer style={styles.flow_container} ref={(instance) => this.otherComponent = instance}>
        </TagContainer>
        <TouchableHighlight onPress={this._onPressButton}><Image source={require('./img/ic_add.png')} style={styles.add_tags_button_view} /></TouchableHighlight>
      </View>
    );
  }
}

export default class OtherComponent extends Component {

    addTag() {
        this.state.tags = this.state.tags.push("plm");
        console.log('success..');
    }

    ....
}

不建议组件之间直接通信,因为它会破坏封装。向组件发送 prop 并让它处理方法内的更改是一个很好的做法 componentWillReceiveProps.

class Main extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: 0 };
    this.handleClick = this.handleClick.bind(this);
  }
   
  handleClick(e) {
    e.preventDefault();
    this.setState({ value: ++this.state.value });
  }
  
  render() {
    return (
      <div>
        <a href="#" onClick={this.handleClick}>click me</a>
        <Child value={this.state.value}/>
      </div>
    );
  }
}


class Child extends React.Component {
  constructor(props) {
    super(props);
    
    this.state = { value: 0 };
  }
  
  componentWillReceiveProps(nextProps) {
    if(nextProps.value !== this.state.value) {
      this.setState({ value: nextProps.value });
    }
  }
  
  render() {
    return <div>{this.state.value}</div>
  }
}


ReactDOM.render(<Main />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"/>

不必在class里面定义函数。这是一个例子

在helpers.js

export async function getAccessKey(){
let accessToken =  await AsyncStorage.getItem(ACCESS_TOKEN);
return accessToken;
}

在调用class.

import { getAccessKey } from '../components/helpers';
...
//inside the method
      let  key = await getAccessKey();

在功能组件中调用远程方法

要对功能组件执行此操作,您必须执行以下操作:

Parent

  1. 使用 useRef():
  2. 在 parent 中给 child 组件一个引用
const childRef = useRef()
// ...
return (
   <ChildComponent ref={childRef} />
)
...

Child

  1. ref传递给构造函数:
const ChildComponent = (props, ref) => {
  // ...
}
  1. 'react' 导入 useImperativeHandleforwardRef:
import React, { useImperativeHandle, forwardRef } from 'react'
  1. 使用 useImperativeHandle 将方法连接到 ref object。

这些方法在内部不可用,因此您可能希望使用它们来调用内部方法。

const ChildComponent = (props, ref) => {
  //...
  useImperativeHandle(ref, () => ({
    // each key is connected to `ref` as a method name
    // they can execute code directly, or call a local method
    method1: () => { localMethod1() },
    method2: () => { console.log("Remote method 2 executed") }
  }))
  //...
  
  // These are local methods, they are not seen by `ref`,
  const localMethod1 = () => {
    console.log("Method 1 executed")
  }
  // ..
}
  1. 导出 child 组件使用 forwardRef:
const ChildComponent = (props, ref) => {
  // ...
}
export default forwardRef(ChildComponent)

综合起来

Child 组件

import React, { useImperativeHandle, forwardRef } from 'react';
import { View } from 'react-native'


const ChildComponent = (props, ref) => {
  useImperativeHandle(ref, () => ({
    // methods connected to `ref`
    sayHi: () => { sayHi() }
  }))
  // internal method
  const sayHi = () => {
    console.log("Hello")
  }
  return (
    <View />
  );
}

export default forwardRef(ChildComponent)

Parent 组件

import React, { useRef } from 'react';
import { Button, View } from 'react-native';
import ChildComponent from './components/ChildComponent';

const App = () => {
  const childRef = useRef()
  return (
    <View>
      <ChildComponent ref={childRef} />
      <Button
        onPress={() => {
          childRef.current.sayHi()
        }}
        title="Execute Child Method"
      />
    </View>
  )
}

export default App

Expo Snacks 上有一个互动演示: https://snack.expo.dev/@backupbrain/calling-functions-from-other-components

此解释修改自此TutorialsPoint article