схема клиента с пользовательским handlerProvider - значения не обновляются - PullRequest
0 голосов
/ 27 августа 2018

При использовании клиентской схемы с пользовательским обработчиком-провайдером все идет хорошо, я могу установить некоторые начальные значения на стороне сервера, и они отображаются в пользовательском интерфейсе. Но при использовании commitLocalUpdate значения не обновляются в пользовательском интерфейсе ...

При использовании стандартного обработчика-провайдера они все же обновляются. А мой пользовательский обработчик - это копия ViewerHandler реле!

Что я пропустил?

Пример:

Разница с примером:

  • В примере используется пользовательский обработчик для поля внутри фрагмента в Query title @__clientField(handle: "draft") , см. Здесь на github . Я пытаюсь использовать его в пользовательском типе ClientState в запросе.

Реле по умолчанию:

  • handlerProvider: предоставляет обработчики по умолчанию для среды
  • Viewer: тип по умолчанию, определенный в схеме по умолчанию
  • ViewerHandler: это обработчик для типа Viewer

Особенности и настройки приложения:

  • handlerProvider: пользовательская версия с дополнительным обработчиком
  • ClientState: дополнительный тип, который я хотел бы использовать
  • ClientStateHandler: пользовательский обработчик, который является копией реле ViewerHandler
  • Я создал clientSchema.graphql в src/ моего проекта, который компилируется реле-компилятором без каких-либо дополнительных настроек.

Этот запрос работает должным образом со стандартным ViewerHandler.

const Comp_Relay = withData(Comp, {
     query: graphql`
        query Comp_Query {
            clientState @__clientField(handle: "clientState") {
                isEditor_locked
            }
            viewer {
                user {
                    role
                }
            }
        }
     `
});

Когда я передаю пользовательский handlerProvider для использования ClientStateHandler, все идет хорошо, и я не получаю сообщение об ошибке. Исходные данные (isEditor_locked: true) установлены правильно. Но обновление интерфейса кажется невозможным.

Примечание: я использую Next.js -> SSR, который происходит здесь.

Гипотеза:

  • Может ли быть связано с тем, что тип ClientState выглядит как тип Circular?
  • Кажется, все работает на стороне сервера, но не на стороне клиента ...
  • Должен ли я где-нибудь промыть магазин? Использовать апдейтер?
  • @__clientField не предназначен для такого использования?

Это обновление, сделанное клиентом с помощью onClick.

commitLocalUpdate(this.props.environment, store => {
    let s = store.get(this.props.clientState.id);
    s.setValue(false, 'isEditor_locked');
});

Вот файл client.graphql в src /:

extend type ClientState {
    isEditor_locked: Boolean
}

Создание среды (содержит пользовательский обработчик Provider, см. Далее ниже)

relayEnvironment = new Environment({
    handlerProvider,
    network,
    store
});

Пользовательский обработчик Provider

import { ConnectionHandler, ViewerHandler } from 'relay-runtime';

const handlerProvider = handle => {
    switch (handle) {
        case 'connection':
            return ConnectionHandler;
        case 'viewer':
            return ViewerHandler;
        case 'clientState':
            return ClientStateHandler;
    }
    throw new Error(`Unknown handle ${handle}`);
};

и, наконец, пользовательский обработчик (копия ViewerHandler из relay-runtime):

import { ROOT_ID } from 'relay-runtime';

const PREFIX = 'client:';

function generateRelayClientID(id, storageKey, index) {
    let key = id + ':' + storageKey;
    if (index != null) {
        key += ':' + index;
    }
    if (key.indexOf(PREFIX) !== 0) {
        key = PREFIX + key;
    }
    return key;
}

const VIEWER_ID = generateRelayClientID(ROOT_ID, 'clientState');
const VIEWER_TYPE = 'Viewer';

const ClientStateHandler = {
    update: function update(store, payload) {
        const record = store.get(payload.dataID);
        if (!record) {
            return;
        }

        const serverViewer = record.getLinkedRecord(payload.fieldKey);

        if (!serverViewer) {
            // If `serverViewer` is null, `viewer` key for `client:root` should already
            // be null, so no need to `setValue` again.
            return;
        }

        // Server data already has viewer data at `client:root:viewer`, so link the
        // handle field to the server viewer record.
        if (serverViewer.getDataID() === VIEWER_ID) {
            record.setValue(null, payload.fieldKey);
            record.setLinkedRecord(serverViewer, payload.handleKey);
            return;
        }
        // Other ways to access viewer such as mutations may have a different id for
        // viewer: synthesize a record at the canonical viewer id, copy its fields
        // from the server record, and delete the server record link to speed up GC.
        const clientViewer = store.get(VIEWER_ID) || store.create(VIEWER_ID, VIEWER_TYPE);

        serverViewer.setValue(true, 'isEditor_locked');

        clientViewer.copyFieldsFrom(serverViewer);

        record.setValue(null, payload.fieldKey);
        record.setLinkedRecord(clientViewer, payload.handleKey);


        // Whatever the value you set for payload.handleKey is what the React component will see.
        // Make sure the root object points to the viewer object as well
        const root = store.getRoot();
        root.setLinkedRecord(clientViewer, payload.handleKey);
    },
    VIEWER_ID
};
...