【问题标题】:Error: Objects are not valid as a React child (found: [object Promise])错误:对象作为 React 子对象无效(找到:[object Promise])
【发布时间】:2021-08-30 03:52:48
【问题描述】:

我正在尝试将我在开始时收到的信息存储到一个名为 t 的变量中,但它没有给我信息。

export const LoginScreen = async() => {
  const [formValues, handleInputChange] = useForm({
    email: '',
    password: ''
  });

  const start = async function () {
    const resp = await fetch('http://localhost:3003/login', {
      method: 'POST',
      body: JSON.stringify({
        'email': formValues.email,
        'password': formValues.password
      }),
      headers: {
        'Content-Type': 'application/json'
      }
    });
  
    const data = await resp.json();
  
    return data;
  }

  const t = await start();

  console.log(t)

  const handleSubmit = (e) => {
    e.preventDefault();
}
```

【问题讨论】:

  • 为什么将异步函数导出为 React 组件?
  • 因为我试图将我收到的信息存储在一个变量中的数据中,如果我不等待,我将无法做到这一点。正确的方法是什么?
  • start async 函数就足够了。请添加整个组件文件来帮助
  • 我已经替换了它,但是在下面我有一个表格,可以让我在电子邮件和密码中添加信息。我想要做的是存储我的获取信息以处理我的对象信息
  • 如果我等待我的变量 t,我会从 Promise {<pending>} 获得信息

标签: reactjs


【解决方案1】:

只需删除组件声明中的异步并重试:

export const LoginScreen = () => {
  const [res, setRes] = useState()
  const [formValues, handleInputChange] = useForm({
    email: '',
    password: ''
  });

  const start = async function () {
    const resp = await fetch('http://localhost:3003/login', {
      method: 'POST',
      body: JSON.stringify({
        'email': formValues.email,
        'password': formValues.password
      }),
      headers: {
        'Content-Type': 'application/json'
      }
    });
  
    const data = await resp.json();
  
    return data;
  }

  start().then((res)=>{
    console.log(res);
    setRes(res);
  });

  const handleSubmit = (e) => {
    e.preventDefault();
}

【讨论】:

  • 我不能这样做,因为 await 没有在我的名为 t 的变量中定义。但是如果我删除它,它就会出来,Promise {<pending>}
  • 嗨@Daniel,这不起作用,因为 await 关键字只允许在异步函数中使用。
  • 如果这对我很有效,但是我在处理它时收到的 res 以便能够对其进行非结构化并在我的 jsx 中使用它
  • @fanjiooJr 我更新了答案,有帮助吗?
【解决方案2】:

将您的异步函数包装在 useEffect() 挂钩中以正确处理副作用。你是否故意遗漏了你想要返回的 JSX?


export const LoginScreen = async() => {
  // --------- EDIT ----------- //
  const [res, setRes] = useState()

  const [formValues, handleInputChange] = useForm({
    email: '',
    password: ''
  });

  // WRAP ASYNC CODE IN USEEFFECT
  useEffect(async() => {
    const start = async function () {
      const resp = await fetch('http://localhost:3003/login', {
        method: 'POST',
        body: JSON.stringify({
          'email': formValues.email,
          'password': formValues.password
        }),
        headers: {
          'Content-Type': 'application/json'
        }
      });
      const data = await resp.json();
      return data;
    }

    // ------- EDIT ------- //
    const t = await start().then(res => {
      console.log(res) 
      setRes(res)     
    });           
  }, [])


  const handleSubmit = (e) => {
    e.preventDefault();
  }

  // Not returning any JSX for this react screen component?
  // return (
  //   <View>
  //     ...
  //.  </View>
  // )
}

【讨论】:

  • 这对我不起作用,因为我想将收到的信息存储在 promise 中,然后能够处理它以在我的 jsx 中显示它。如果我下面有jsx,就不要放了
  • "如果我在下面有 jsx,就不要放它"
  • 编辑了代码以便于使用 useState。
【解决方案3】:

所以你可以做的是你可以将异步函数转换成一个promise,它会等待执行完成。错误处理的执行如下。

export const LoginScreen = async () => {
  const [formValues, handleInputChange] = useForm({
    email: "",
    password: "",
  });

  const start = function () {
    //   converting into a async promise
    return new Promise(async (resolve, reject) => {
      try {
        const resp = await fetch("http://localhost:3003/login", {
          method: "POST",
          body: JSON.stringify({
            email: formValues.email,
            password: formValues.password,
          }),
          headers: {
            "Content-Type": "application/json",
          },
        });

        const data = await resp.json();
        //   resolving on success

        resolve(data);
      } catch (error) {
        //   rejecting on failures
        reject(error);
      }
    });
  };

  // Now this will await the start function to be completed.
  const t = await start();

  console.log(t);

  const handleSubmit = (e) => {
    e.preventDefault();
  };
};

解释:由于我们已经在异步函数内部等待,JS 倾向于跳过它,除非它是一个需要明确解决的承诺。因此,现在将您的函数转换为 Promise,我们可以等待它被解析。

我为 NODE 做了一个简单的工作示例,

const LoginScreen = async () => {
  const start = function () {
    //   converting into a async promise
    return new Promise(async (resolve, reject) => {
      try {
        setTimeout(() => {
          return("Hello");
        }, 3000);
      } catch (error) {
        //   rejecting on failures
        reject(error);
      }
    });
  };

  const t = await start();

  console.log(t);

  const handleSubmit = (e) => {
    e.preventDefault();
  };
};

LoginScreen();

如果你看到了,该函数现在会等待 3 秒,然后在启动函数解析后将数据保存在 t 中

沙盒链接的代码更新

import { useForm } from "./useForm";

export const LoginScreen = () => {
  const [formValues, handleInputChange] = useForm({
    email: "",
    password: ""
  });
  // const formValues = { email: "", password: "" };

  const start = function () {
    // -------------- important -------------------
    return new Promise(async (resolve, reject) => {
    // -------------- important -------------------

      const resp = await fetch("http://localhost:3003/login", {
        method: "POST",
        body: JSON.stringify({
          email: formValues.email,
          password: formValues.password
        }),
        headers: {
          "Content-Type": "application/json"
        }
      });

      const data = await resp.json();

      resolve(data);
    });
  };

  const handleSubmit = async (e) => {
    // -------------- important -------------------
    console.log("Submitting");
    e.preventDefault();

    const t = await start();
    console.log(t);
    // -------------- important -------------------

  };

  return (
    <div>
      <h1>Login</h1>

      <form onSubmit={handleSubmit}>
        <input
          autoComplete="off"
          type="email"
          placeholder="Enter email"
          name="email"
          value={formValues.email}
          onChange={handleInputChange}
          required
        />
        <input
          autoComplete="off"
          type="password"
          placeholder="Enter password"
          name="password"
          value={formValues.password}
          onChange={handleInputChange}
          required
        />

        <button type="submit">Login</button>
      </form>
    </div>
  );
};

这是有效的,我已经评论了一些部分以加快开发,您取消评论并继续前进。现在它们应该可以工作了。

现在您肯定会将值分配给“t”。确保你做了一些错误处理,然后你可以将此令牌传递给主函数,你可以使用回调方法,也可以使用全局上下文并以更好的方式管理状态。

如果仍然失败,请告诉我,我们可以找到更好的解决方案。 编码愉快。

【讨论】:

  • 如果它一直让我遇到同样的错误,因为我想要做的是存储它,然后能够对对象进行非结构化
  • 嗨@fanjiooJr,我无法得到评论。
  • 如果你可以把它放在一个 sandbox.io 中并使用一些虚拟 API 来使用它会更好,因为它会更容易提供帮助。
  • 我正在登录,如果电子邮件和密码正确,帖子会在 resp 中返回一个令牌。所以我需要解构获得的对象,所以我必须将我的信息存储在一些变量中。正如它在你身上的样子,但这个错误让我感到Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
  • 你能更新你的解构逻辑吗?
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 2016-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 2018-01-12
相关资源
最近更新 更多