React JS变量和文本字段未更新

Posted

技术标签:

【中文标题】React JS变量和文本字段未更新【英文标题】:React JS variable and text field not updating 【发布时间】:2021-01-14 04:24:36 【问题描述】:

我目前正在使用 Polaris 组件来构建一个 shopify 应用。本质上,我想根据以前的值更新字段。我有一个文本框设置到的 Google Firebase 连接,然后您可以编辑文本框 - 所以文本的初始状态是数据库中的内容。然后你按下提交并更新数据库。

更新很好,我可以从数据库中获取数据并将其加载到框中,但是当我这样做时,任何时候我都可以通过将文本框设置为数据来使用检索到的内容(使用 setEmail(loadedEmail); )我无法编辑该框。每当我删除、键入、粘贴或任何内容时,它都会在一瞬间恢复到在数据库中找到的表单。就好像每次我在框中输入时,它都会重新加载数据库,并且它最初的任何内容都无法更改。

这完全把我难住了。这是代码的当前状态 - 到顶部是我认为问题所在,以及“setEmail”部分:

export default function FormOnSubmitExample() 
  let loadedEmail = "Enter Email"; //this is only seen if the database cannot find records (becuase it is the first time they have seen the screen)

  const db = firebase.firestore();  
  const docRef = db.collection('example').doc('testuser1');
  docRef.get().then(function(doc) 
    if (doc.exists) 
      console.log("Document data:", doc.data().email);

      loadedEmail = doc.data().email; // set the inital textbox to this (but does not work - "Enter Email" from the declaration is seen in the textbox instead, not whatever this is as if it has not worked.)

      setEmail(loadedEmail); // When this is not commented out, I cannot edit the textbox and the data from the database cannot be found. Without this command, despite the 'state' variable being set to the same data, the textbox will not update.

     else 
      console.log("No such document!");
    
  ).catch(function(error) 
    console.log("Error getting document:", error);
  );



  const [email, setEmail] = useState(loadedEmail); // originally just '' as a blank field, so now holds the variable which was entered previously and now stored in db but only if 'setEmail' is used at the top

  let updater = email; // this is used because I cannot pass 'email' from the textbox into function otherwise
  const handleSubmit = useCallback((_event) => 
    setEmail('');
    const db = firebase.firestore();

      db.collection('example').doc('testuser1').update(
        email: updater  // this is used because I cannot pass 'email' from the textbox into function otherwise
      )
      .then(() => alert("Updated Database"))
      .catch(() => alert('Something Went wrong'))
  , []);
    
  const handleEmailChange = useCallback((value) => setEmail(value), []);

  return (
    <Form onSubmit=handleSubmit>
      <FormLayout>

        <TextField
          value=email
          onChange=handleEmailChange
          label="Email"
          type="email"
          helpText=
            <span>
              We’ll use this email address to inform you on future changes to
              Polaris.
            </span>
          
        />

        <Button submit>Submit</Button>
      </FormLayout>
    </Form>
  );

我完全被难住了。我对 React 很陌生,但我有几年的其他语言编程经验,所以我对为什么变量没有更新感到困惑,但这可能是因为我遗漏了一些明显的东西!我的猜测是,当不使用“setEmail”时,它首先加载文本框,因此一旦更新一次,它就会改变显示 - 允许我编辑它但不显示数据库信息。当使用 'setEmail' 时,它会更新很多次,阻止我更改它,或者出于某种原因,不允许我编辑它。

我认为这与这个答案/问题有关 -> https://***.com/a/55266240/13964958

感觉就像我快到了,但我不能同时编辑它并拥有数据!

【问题讨论】:

【参考方案1】:

我认为这里的问题是您在每次重新渲染发生时都会调用组件中的数据库。所以这发生了:

    用户更改文本区域(调用了handleEmailChange) 状态已更新,触发重新渲染(由于 setEmail(value) ) 您的所有代码都会再次运行(包括 db 调用) 在 db 调用中,您再次使用 setEmail 将 textarea 设置回 DB 中的内容

所以你可以在这里做的是使用 useEffect 钩子,并且只在挂载时运行以获取初始值。

useEffect(() =>  db call , [])

最后的空数组让 react 知道你只希望它在组件初始渲染时运行。

这是一个非常简单的代码笔,显示了我的意思:https://codepen.io/serp002/pen/mdPgYma

您可以看到,每次您键入内容时,控制台日志都会出现,在您的情况下,这实际上是一个将状态重置回数据库中的值的函数。

如果您将控制台日志添加到您的数据库调用中,您应该能够在每次更改文本区域中的值时看到它被调用。

【讨论】:

以上是关于React JS变量和文本字段未更新的主要内容,如果未能解决你的问题,请参考以下文章

React 中的状态未更新 [重复]

RxSwift - 当 UITextField 以编程方式更新时,UILabel 字段未更新

状态更改后,上下文未更新 React Native 中的文本

React.js - 功能组件中的状态未更新[重复]

选择器视图 - 文本字段未更新

React JS:调用 setState 后组件未更新