Как я могу использовать значение провайдера для useMutation, а также затем отправить изменения в состояние? - PullRequest
0 голосов
/ 04 февраля 2020

Я хотел бы использовать значение Context.Provider для обработки как изменения, так и отправки аналогичных изменений. Я читал о методе React-Apollo onComplete, но я не уверен, какой подход будет охватывать больше случаев, когда мне нужно и мутировать, и отправлять состояние. Вот что у меня есть:

const CartContext = React.createContext<{
  state: State
  dispatch: Dispatch<AnyAction>
  cartApi: any
}>({ state: initialState, dispatch: () => null, cartApi: mutateUserProductsAndUpdateCart })

function CartProvider({ children }: { children?: React.ReactNode }) {
  const [state, dispatch] = useReducer<Reducer<State, AnyAction>>(reducer, initialState)

  // feel like i need to do something with the hook here to avoid invariant violation side effects
  const [updateUserProducts] = useUpdateUserProducts()
  return (
    <CartContext.Provider value={{ state, dispatch, cartApi: mutateUserProductsAndUpdateCart}}>
      {children}
    </CartContext.Provider>
  )
}
export const useCartState = () => useContext(CartContext)

И вот что я бы хотел бы сделать с моим mutateUserProductsAndUpdateCart:

const mutateUserProductsAndUpdateCart = async (_mutation: any, _mutationParams: any, _dispatchObject: AnyObject) => {
  // apollo mutation
  const updateUserProductsResult = await updateUserProducts(_mutationParams)

  if (updateUserProductsResult.error) throw Error("wtf")

  // useReducer dispatch
  dispatch(_dispatchObject)

  return
}

и вот как я хотел бы получить к нему доступ это на другом компоненте:

const { cartApi } = useCartState()
const addProductToCart = async () => {
  const result = await cartApi({
    mutation,
    mutationVariables,
    dispatchObject})
}

Я чувствую, что эта статья - своего рода направление, в котором я должен идти, но я очень потерян в реализации здесь. Спасибо за чтение.

1 Ответ

0 голосов
/ 04 февраля 2020

Я не уверен, что это прямо отвечает на ваш вопрос, но рассматривали ли вы просто использование Apollo Client? Похоже, вы пытаетесь сделать две вещи:

  1. Сохранить элементы, добавленные в корзину на сервер
  2. Обновить корзину локально в кеше

Кажется, что вы можете вообще пропустить создание своего собственного контекста и просто создать хук для изменения (сохранение элементов корзины), а затем обновить локальный кэш для элементов корзины. Примерно так:

import gql from 'graphql-tag';
import useMutation from '@apollo/client';

export const mutation = gql`
  mutation($items: [CartItem]!) {
    saveCartItems(items: $items) {
      id
      _list_of_properties_for_cache_update_
    }
  }
`;

export const useSaveCartItems = mutationProps => {
  const [saveCartItems, result] = useMutation(
    mutation,
    mutationProps
  );

  return [
    items => {
      saveCartItems({
        update: (cache, { data }) => {
          const query = getCartQuery; // Some query to get the cart items from the cache
          const results = cache.readQuery({ query });

          // We need to add new items only; existing items will auto-merge
          // Get list of new items from results
          const data = []; // List of new items; IMPLEMENT ME!!!

          cache.writeQuery({ query, data });
        },
        variables: { items },
      });
    },
    result,
  ];
};

Затем в вашем хуке useCartState вы можете просто запросить локальный кеш для элементов, используя тот же запрос, который вы использовали для update, и вернуть его. Используя функцию update, вы можете исправить свой локальный кеш, и любой может получить к нему доступ из любой точки мира, просто используйте хук. Я знаю, что это не совсем то, что вы просили, но я надеюсь, что это поможет.

Клиентская документация Apollo по обработке этого может быть найдена здесь .

...