【问题标题】:how to initialize useState with apollo graphql query如何使用 apollo graphql 查询初始化 useState
【发布时间】:2023-03-15 20:00:01
【问题描述】:

如何使用useState 并在组件呈现之前将其设置为从graphql 接收到的值?

我试过了:

  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  

  const [me] = useQuery(gql`
    query Me {
      me {
        id
        name
        email
      }
    }
  `);

  useEffect(() => {
    (async () => {
      const { data } = await me();

      if (data) {
        setName(data.me.name);
        setEmail(data.me.email);
      }
    })();
  }, []);

并收到此错误:

TypeError: Object is not a function
Profile
src/pages/Profile.js:51
  48 | const [currentPasswordValid, setCurrentPasswordValid] = useState(false);
  49 | const [open, setOpen] = useState(false);
  50 | 
> 51 | const [me] = useQuery(gql`
     | ^  52 |   query Me {
  53 |     me {
  54 |       id

我尝试这样做的原因是将表单输入的值设置为当前用户值:

<TextField value={name} onChange={(e) => setName(e.target.value)} />

【问题讨论】:

  • FC fn body 都是关于渲染的,它不能被停止、屈服或……你只能有条件地阻止一些部分——如果数据没有准备好,只需显示/返回“加载”跨度>

标签: reactjs graphql apollo react-apollo


【解决方案1】:

您似乎使用了错误的钩子。 useQuery 会在组件挂载后自动执行。它将返回您可以使用的 dataloadingerror 属性(如果您查看文档,还有更多属性,但这些是基本属性)。

如果您想手动触发查询,您可以使用useLazyQuery 挂钩,该挂钩将返回上述属性和可用于执行查询的回调。

使用useQuery,您的代码可以如下所示:

const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  

  const { data, loading } = useQuery(gql`
    query Me {
      me {
        id
        name
        email
      }
    }
  `);

  if(loading) {
    return <div>loading...</div>;
  }

  return <TextField value={data.me.name} onChange={(e) => setName(e.target.value)} />;

如果您更喜欢使用惰性查询,您的代码可以如下所示:

  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  

  const [me, { data }] = useLazyQuery(gql`
    query Me {
      me {
        id
        name
        email
      }
    }
  `);

  useEffect(() => {
    (async () => {
      await me();
    })();
  }, []);

  useEffect(() => {
    if (data) {
      setName(data.me.name);
      setEmail(data.me.email);
    }
  }, [data])

我个人更喜欢在不必要的时候避免使用惰性查询。

【讨论】:

  • 这对我不起作用Unhandled Rejection (TypeError): Cannot destructure property 'data' of '(intermediate value)' as it is undefined. (anonymous function) src/pages/rooms/UpdateRoom.js:77 74 | `); 75 | 76 | useEffect(async () =&gt; { &gt; 77 | const { data } = await room({ | ^ 78 | variables: { id: match.params.id }, 79 | }); 80 |
  • 我认为 { data } 仅在您创建查询时可用,而不是在运行时可用。我已经相应地更新了我的答案。但同样,第一个选项(不使用惰性查询)更干净、更安全。
  • 第一个选项有效,但由于某种原因,我无法键入或更改输入值。输入保持data.me.name,无法更改。
  • 是的,输入是不可变的。如果您想更改它,我建议您进行突变以将更改告知远程服务器,然后重新获取您的查询,这样服务器就可以作为您的唯一真实来源。
  • 如果你还想在本地改,你可以复制对象:const newData = { ...data };(这是浅拷贝,看看是否适合你)。如果您更改newData,它不会反映在您的服务器上。
猜你喜欢
  • 2019-12-18
  • 1970-01-01
  • 2021-04-19
  • 2016-11-30
  • 2018-04-28
  • 1970-01-01
  • 2021-01-01
  • 2018-06-09
  • 2018-10-19
相关资源
最近更新 更多