是否有一个函数返回一个承诺,当在 React Native 中应用了对组件的任何未决更改时,该承诺得到解决?

Posted

技术标签:

【中文标题】是否有一个函数返回一个承诺,当在 React Native 中应用了对组件的任何未决更改时,该承诺得到解决?【英文标题】:Is there a function that returns a promise which gets resolved when any pending changes to a component have been applied in React Native? 【发布时间】:2021-07-11 11:50:28 【问题描述】:

我想显示一个自定义输入组件,然后在单击按钮时调用它的方法:

const Parent = () => 
  const customInputRef = useRef(null);

  const [customInputVisible, setCustomInputVisible] = useState(false);

  async function onPress() 
    setCustomInputVisible(true);

    await resolvePendingChanged(); // customInput is not null and can be accessed

    customInputRef.current.customMethod();
  

  return (
    <View>
      <Button onPress=onPress>Press me!</Button>

      customInputVisible && <CustomInput ref=customInputRef />
    </View>
  );


我看到人们使用custom forceUpdate function 来触发组件更新,但这对我来说并没有真正的帮助。

在Svelte 中有这个"tick" lifecycle hook 正是我需要的。

它返回一个承诺,该承诺会在任何未决状态时立即解决 更改已应用于 DOM(或立即,如果没有 等待状态更改)。

React 中是否有与 Svelte 的 tick 等效的方法,如果没有,我如何在 React 中解决这个问题?

【问题讨论】:

【参考方案1】:

您可以创建一个使用callback ref 的自定义钩子来设置实际的引用,并解决一个承诺:

const  forwardRef, useImperativeHandle, useRef, useState, useCallback, useMemo  = React;

const CustomInput = forwardRef((props, ref) => 
  const inputRef = useRef();
  
  useImperativeHandle(ref, () => (
    customMethod: () => 
      inputRef.current.focus();
    
  ), []);
  
  return <input ref=inputRef />;
);

class Deferred 
  constructor() 
    this.promise = new Promise((resolve, reject) => 
      this.resolve = resolve;
      this.reject = reject;
    );
  


const waitForComponent = () => 
  const componentRef = useRef(null);
 
  return useMemo(() => 
    let deferred = new Deferred();
    
    return 
      waitLoad(ref) 
        componentRef.current = ref;
        
        if (ref) deferred.resolve();
        else deferred = new Deferred(); // create new Promise when ref is null
      ,
      isLoaded: () => deferred.promise,
      componentRef
    ;
  , []);


const Parent = () => 
  const  waitLoad, componentRef, isLoaded  = waitForComponent();
  const [customInputVisible, setCustomInputVisible] = useState(false);

  function onPress() 
    setCustomInputVisible(visible => !visible);
     
    // use async here - SO snippet doesn't support async await
    isLoaded().then(() => componentRef.current.customMethod());
  

  return (
    <div>
      <button onClick=onPress>Press me!</button>

      customInputVisible && <CustomInput ref=waitLoad />
    </div>
  );
;

ReactDOM.render(
  <Parent />,
  root
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

【讨论】:

非常感谢您的回复!但是,这仅在您希望在 customInputVisibletrue 时始终调用 customMethod() 时才有效。但是,这不是我的情况。我想确保 customMethod() 仅被称为 onPress 而不是在 customInputVisible 更改时。 它有效,非常感谢!这是一个超级聪明的解决方案,虽然我很惊讶你必须为如此简单的任务编写如此多的逻辑。这可以通过 Svelte 和 Angular 中的一行来解决。还是不明白为什么 React 是最受欢迎的前端库。 ? 因为它是 React 中的一个边缘案例,你很少遇到。另外,现在你有了一个可重复使用的钩子,如果你以后遇到类似的问题,你可以使用它。 嗯,也许你是对的,虽然对我来说看起来很常见。我必须在几个不同的项目中执行此操作,例如,关注嵌套输入,或者在这种情况下,我必须在单击“回复”按钮时添加用户标签 (@user)。无论如何,再次非常感谢!节省了我很多时间!

以上是关于是否有一个函数返回一个承诺,当在 React Native 中应用了对组件的任何未决更改时,该承诺得到解决?的主要内容,如果未能解决你的问题,请参考以下文章

查找函数是不是会返回承诺的方法

从 .map() 方法中的调度函数返回承诺

React Native AsyncStorage getItem 返回承诺而不是值

.catch() 甚至通过 fetch() 从另一个承诺中捕获所有错误

使用 AngularJS 立即返回一个已解决的承诺

是否有与 dplyr::coalesce() 相反的 R 函数?