如何将GraphQL + Relay检索到的数据转换为正常的React状态?

问题描述 投票:0回答:1

文档中的示例

import type {AppQueryType} from 'AppQueryType.graphql';

const React = require('React');

const {graphql, useQueryLoader, usePreloadedQuery} = require('react-relay');

const AppQuery = graphql`
  query AppQuery($id: ID!) {
    user(id: $id) {
      name
    }
  }
`;

type Props = {
  initialQueryRef: PreloadedQuery<AppQueryType>,
};

function NameLoader(props) {
  const [queryReference, loadQuery] = useQueryLoader(
    AppQuery,
    props.initialQueryRef, /* e.g. provided by router */
  );

  return (<>
    <Button
      onClick={() => loadQuery({id: '4'})}
      disabled={queryReference != null}
    >
      Reveal your name!
    </Button>
    <Suspense fallback="Loading...">
      {queryReference != null
        ? <NameDisplay queryReference={queryReference} />
        : null
      }
    </Suspense>
  </>);
}

function NameDisplay({ queryReference }) {
  const data = usePreloadedQuery(AppQuery, queryReference);

  return <h1>{data.user?.name}</h1>;
}

太复杂了。首先,我不想将初始组件拆分为

NameLoader
NameDisplay
只是因为这样对于 Relay 来说方便。其次,即使我有子组件,我也不希望
PreloadedQuery
位于
props
之中,因为它是 Relay 和简单 React 组件的紧密结合(这意味着用其他组件替换 Relay 将需要所有组件的编辑,例如
NameDisplay
)。相反,我想通过
props
传递普通数据,例如
user
对象。

所需的代码将类似于:

import type {AppQueryType} from 'AppQueryType.graphql';

const React = require('React');

const {graphql, useQueryLoader, usePreloadedQuery} = require('react-relay');

const AppQuery = graphql`
  query AppQuery($id: ID!) {
    user(id: $id) {
      name
    }
  }
`;


function NameLoader(props) {
  const rawUser = useMagic(AppQuery);
  const [ user, setUser ] = toLocalState(rawUser);

  return (<>
    <Button
      onClick={() => loadQuery({id: '4'})}
      disabled={queryReference != null}
    >
      Reveal your name!
    </Button>
    <h1>{user.name}</h1>;
  </>);
}

我知道数据获取是异步的,但这并不意味着真正建议的唯一正确的解决方案。

const [ user, setUser ] = toLocalState(rawUser);
行,我想像正常本地状态一样使用
user
变量。在此示例中,我不关心
user
的本地更改不会反映在服务器端的
user
上 - 当我准备好反映时,我将调用适当的突变。

用什么来代替

useMagic
toLocalState

reactjs graphql relayjs
1个回答
0
投票

您似乎正在寻找一种方法,以更直接的方式管理使用 Relay 从 GraphQL 检索的数据,而不依赖于 Relay 钩子提供的结构。您想要将数据转换为更传统的 React 状态模式。虽然这种方法可能无法充分利用 Relay 的优化,但您可以通过结合

useLazyLoadQuery
钩子和本地 React 状态来实现您想要的目标。

以下是如何使用示例实现这一目标:

import type { AppQueryType } from 'AppQueryType.graphql';
import React, { useState } from 'react';
import { graphql, useLazyLoadQuery } from 'react-relay';

const AppQuery = graphql`
  query AppQuery($id: ID!) {
    user(id: $id) {
      name
    }
  }
`;

function NameLoader() {
  const [userId, setUserId] = useState(null); // User ID state
  const data = useLazyLoadQuery<AppQueryType>(AppQuery, { id: userId });

  return (
    <>
      <Button onClick={() => setUserId('4')} disabled={userId != null}>
        Reveal your name!
      </Button>
      {data.user ? <h1>{data.user.name}</h1> : null}
    </>
  );
}

在此示例中,我使用

useLazyLoadQuery
钩子在用户 ID 更改时获取数据。单击该按钮时,
userId
状态会更新,从而导致查询获取用户数据。获取的用户数据存储在
data
变量中。

请注意,通过使用这种方法,您并没有充分利用 Relay 的优化,但它提供了更熟悉的 React 状态管理方法。如果您稍后决定更广泛地使用 Relay 的优化,您可能需要重构您的组件以更严格地遵守 Relay 的约定。

© www.soinside.com 2019 - 2024. All rights reserved.