【问题标题】:Calling a children method of a functional component from parent从父级调用功能组件的子级方法
【发布时间】:2021-05-17 11:19:36
【问题描述】:

我没有使用类,我想学习如何手动操作。我正在处理登录屏幕。 https://snack.expo.io/@ericsia/call-function-from-child-component 如果您想向我展示您的代码,您需要保存并分享链接。所以我想要一个显示文本框的功能组件(假设ChildComponent作为函数名称,所以export ChildComponent)。
所以在 Parent/Screen1 我有类似的东西吗?

import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';

// You can import from local files
import ChildComponent from './components/ChildComponent';

export default function App() {
  
  function checkSuccess()
  {
    // call helloWorld from here
  }
  return (
    <View style={styles.container}>
   
        <ChildComponent />
    
        <TouchableOpacity style={styles.button}
        onPress={ checkSuccess } >
        <Text>helloWorld ChildComponent</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  button: {
    alignItems: "center",
    backgroundColor: "#DDDDDD",
    padding: 10
  },
});

所以如果结果是无效的,我想显示一个小的红色错误消息。 something like this 我的方法是,如果我可以从ChildComponent 调用一个函数,那么我仍然可以解决它。
我用谷歌搜索了它,提供的大部分解决方案都是针对课堂的。 我试过useEffectReact.createRefuseImperativeHandle,但没有成功。
首先,我只是想打电话给helloWorld()

import * as React from 'react';
import { TextInput , View, StyleSheet, Image } from 'react-native';

export default function ChildComponent() {
  function helloWorld()
  {
    alert("Hello World");
  }
  return (<TextInput placeholder="Try to call helloWorld from App.js"/>);
}

另一个问题,如果我的 ChildComponent 中有一个文本框,我如何从父级检索文本/值?

【问题讨论】:

  • 这真的很痛苦。你最好在父级App 中声明helloWorld 并将其作为道具传递给ChildComponent。我在这里的回答解释了如何以艰难的方式做到这一点:stackoverflow.com/a/64491870/10431574

标签: reactjs typescript react-native


【解决方案1】:

简单的方法:传递道具

您可以将helloWorld 函数向上移动到父组件,然后将其作为道具传递给子组件。这样两个组件都可以调用它。当你要传递一个函数时,我建议使用arrow function,尽管在这种情况下并不重要。

父母

export default function App() {
  const helloWorld = () => {
    alert('Hello World');
  }
  const checkSuccess = () => {
    helloWorld();
  }

  return (
    <View style={styles.container}>
      <ChildComponent helloWorld={helloWorld} />
      <TouchableOpacity style={styles.button} onPress={checkSuccess}>
        <Text>helloWorld ChildComponent</Text>
      </TouchableOpacity>
    </View>
  );
}

孩子

const ChildComponent = ({ helloWorld }) => {
  // could do anything with helloWorld here

  return <TextInput placeholder="Try to call helloWorld from App.js" />;
};

艰难之路:参考转发

如果你想将函数保留在子组件中,那么你需要经历很多麻烦。我不推荐这种方法。

您必须完成所有这些步骤:

  • 使用useRef在父级中创建ref对象:const childRef = React.useRef();
  • 将 ref 作为道具传递给孩子:&lt;ChildComponent ref={childRef} /&gt;
  • 在子组件 ref 的当前值上调用函数,如果尚未设置 .current,请使用 ?. 以避免错误:childRef.current?.helloWorld();
  • 通过使用forwardRefReact.forwardRef( (props, ref) =&gt; { 接受孩子中的ref 属性
  • 通过使用useImperativeHandlehelloWorld函数公开为子组件的实例变量:React.useImperativeHandle(ref , () =&gt; ({helloWorld}));

家长:

export default function App() {
  const childRef = React.useRef();

  function checkSuccess() {
    childRef.current?.helloWorld();
  }

  return (
    <View style={styles.container}>
      <ChildComponent ref={childRef} />
      <TouchableOpacity style={styles.button} onPress={checkSuccess}>
        <Text>helloWorld ChildComponent</Text>
      </TouchableOpacity>
    </View>
  );
}

孩子:

const ChildComponent = React.forwardRef((props, ref) => {
  function helloWorld() {
    alert('Hello World');
  }

  React.useImperativeHandle(ref, () => ({ helloWorld }));

  return <TextInput placeholder="Try to call helloWorld from App.js" />;
});

编辑:Expo Link

【讨论】:

  • 它不像helloWorld那么简单,你看看输入有没有错对,我想在文本框下面显示一个可见的红色文本,所以函数必须在ChildComponent中
  • 我尝试了 useImperative 但失败了,但我非常感谢您的详细指南。如果可能的话,您可以从上面的链接尝试,保存并分享链接
  • 确定:snack.expo.io/P61KJDOKr 我没有包含 typescript 注释,因为您在原始版本中没有使用 typescript。
  • 你太棒了,太棒了。但我似乎无法让打字稿版本正常工作。无论如何,非常感谢!
猜你喜欢
  • 1970-01-01
  • 2015-07-28
  • 2020-01-22
  • 1970-01-01
  • 1970-01-01
  • 2019-12-14
  • 2019-03-01
  • 1970-01-01
  • 2020-05-06
相关资源
最近更新 更多