Diseñar las mutaciones de db y state y las solicitudes de un constructor de formularios en reaccionar con graphQL, faunaDB, nextJS y Apollo

0

Estoy trabajando en una próxima aplicación JS, React, Apollo, graphQL, faunaDB. Estoy tratando de diseñar cómo funcionaría un constructor de formularios con sus mutaciones en fauna a través de graphQL. Puedo ejecutar mutaciones desde el patio de recreo y puedo consultar desde la interfaz y construir mi formulario. Interacción vista aquí https://www.loom.com/share/7f7d1e1231d445f2be6b5db2c81239b6

Ahora estoy bastante seguro de que puedo averiguar cómo ejecutar una mutación en la interfaz, mi preocupación es cuándo ejecutarla. Mira, tengo el siguiente código. Que consulta faunaDB y genera elementos de entrada del estado (que se completa con la consulta) (actualmente solo los del tipo texto) y le permite agregar nuevos tipos de entrada de formulario al estado, lo que provoca una repetición y muestra una nueva entrada de formulario. elemento. Todo esto está muy bien.

import { useQuery, gql } from "@apollo/client";
import { useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";

const INPUT_VALUES = gql`
  query GetInputValues {
    allFormInputVals {
      data {
        name
        _id
        type
      }
    }
  }
`;

const Home = () => {
  const { loading, error, data } = useQuery(INPUT_VALUES);

  const [formState, setFormState] = useState(undefined);

  useEffect(() => {
    setFormState(data?.allFormInputVals?.data);
  }, [data]);

  const addInput = () => {
    const blanktext = {
      __typename: "FormInputType",
      name: "Product Image",
      _id: uuidv4(),
      type: "text",
    };
    console.log(formState);
    setFormState([...formState, { ...blanktext }]);
  };

  if (loading) return <p>Loading...</p>;

  if (error) return <p>Error: {error.message}</p>;

  return (
    <>
      <form>
        <input type="button" value="Add Form Input" onClick={addInput} />
        {formState?.map((val, idx) => {
          const nameId = `name-${idx}`;
          const typeId = `type-${idx}`;
          return (
            <div key={val._id}>
              {val.type === "text" && (
                <>
                  <label htmlFor={nameId}>{`Name #${idx + 1}`}</label>

                  <input
                    type="text"
                    name={nameId}
                    id={nameId}
                    className={val.type}
                  />
                  <label htmlFor={typeId}>{`Type #${idx + 1}`}</label>

                  <select name={typeId} id={typeId} className={val.type}>
                    {data.allFormInputVals.data.map((item) => {
                      return (
                        <option key={item._id} value={item.type}>
                          {item.type}
                        </option>
                      );
                    })}
                  </select>
                </>
              )}
            </div>
          );
        })}
      </form>
    </>
  );
};

export default Home;

Sin embargo, mis opciones de mutación en el patio de recreo parecen estar limitadas a solo agregar uno, lo que se llama un documento a la vez, que es un objeto. Si registro en la consola mi estado que quiero agregar a la base de datos, se verá de la siguiente manera. Ahora puedo hacer una mutación en el patio de recreo donde puedo agregar uno de estos objetos. Pero quiero poder agregarlos todos a la vez. En una operación de guardado. Quiero hacer esto porque no quiero ejecutar una solicitud de cada adición al formulario, quiero usar el estado de reacción para manejar el formulario hasta el final y luego hacer mi solicitud de base de datos.

[
   {
      "__typename":"FormInputVal",
      "name":"name",
      "_id":"291541872966369805",
      "type":"text"
   },
   {
      "__typename":"FormInputVal",
      "name":"name",
      "_id":"291541888089981453",
      "type":"text"
   },
   {
      "__typename":"FormInputVal",
      "name":"Product Image",
      "_id":"255f95e0-bff1-4e75-81fc-d6f3f9a72446",
      "type":"text"
   }
]

Ahora he creado un esquema graphQL que tiene usuarios, que pueden tener muchos formularios, y formularios que pueden tener muchas entradas. Eso parece. La directiva @relation es específica de faunaDB. Funciona como lo espero, más allá de este problema de mutación que he mencionado.

type Form {
  name: String!
  index: Int!
  user: User
  formInputVals: [FormInputVal!] @relation
}

type FormInputVal {
  name: String!
  index: Int!
  type: String!
  formRoot: Form!
}

type User {
  name: String!
  email: String!
  password: String!
  forms: [Form] @relation
}

type Query {
  allForms: [Form!]
  allUsers: [User!]
  allFormInputVals: [FormInputVal!]
}

Vea que puedo mutar la base de datos con lo siguiente. Donde selecciono un formulario específico y agrego una entrada, lo que provoca una repetición de la interfaz y aparece la entrada del formulario. Todo esto está muy bien. Este es un ejemplo de mutación de ese tipo.

mutation{
  createFormInputVal(data:
    {formRoot:{connect:"291541554941657608"},name:"name",type:"text",index:0}){
    name
    type
    index
    formRoot{
      name
    }
  }
}

Pero aquí es donde radica la raíz del problema.

Quiero tomar ese estado creado por react y agregarlo a una colección faunaDB que se llama formInputValesquema graphql y se asigna a las colecciones db.

Hablé con el soporte de Fauna y mencionaron una directiva @resolver donde puedo ejecutar una función DB y agregar varios documentos (objetos) a la vez hasta ahora, la sintaxis de la función lambda para faunaDB está por encima de mi comprensión. Mencionaron este artículo para la función https://docs.fauna.com/fauna/current/tutorials/ecommerce#function y este para el solucionador https://forums.fauna.com/t/placing-an-index- en-un-campo-en-un-tipo-incrustado / 778/4

Aclaremos

¿Me estoy acercando a esto bien? Estoy abierto a cambiar el esquema. ¿Qué harías si quisieras resolver este problema con enfoques alternativos o el mismo enfoque, pero con una pieza faltante que no entiendo?

¿Por qué no puedo simplemente pasar una matriz de objetos a la mutación para el ID de formulario correcto, y agrega tantos documentos a la colección en una consulta? ¿Existe algún tipo de práctica general para crear una forma generativa como esta?

Ok, gracias por la ayuda de antemano.

ACTUALIZAR:

He probado la siguiente mutación pero no funciona. Tiene el siguiente errorUnknown argument 'formInputVal' on field 'createFormInputVal' of type 'Mutation'

const ADD_INPUT_VALUES = gql`
  mutation AddInputValues($formInputVal: FormInputValInput!) {
    createFormInputVal(formInputVal: $formInputVal) {
      name
    }
  }
`;

const [createFormInputVal, { data: createInputData }] = useMutation(
    ADD_INPUT_VALUES
  );

...
<form
        onSubmit={async (e) => {
          e.preventDefault();
          const res = await createFormInputVal({
            variables: formState,
          }).catch(console.error);
          console.log(res);
        }}
      >
...

dieciséis
  • nunca has oído hablar de los tipos de entrada, ¿verdad? graphql.org/learn/schema/#input-types
    xadm
    26 de febrero a las 20:10
  • No, no he oído hablar de estos, parece que podría ser lo que estoy buscando, tendré que mirar algunos ejemplos más para ver cómo los usaría, gracias. 26 feb a las 20:52
  • Todavía estoy un poco atascado en cómo escribiría la mutación usando el tipo de entrada, faunaDB dice que los tipos de entrada se generan automáticamente y se usan en las mutaciones, pero no estoy seguro de cómo le pasaría un objeto. Cualquier idea docs.fauna.com/fauna/current/api/graphql/input 26 feb a las 21:07
  • Veo este tipo de entrada en mis documentos FormInputValInputen el patio de recreo, pero no estoy seguro de cómo usarlo en una mutación. 26 feb a las 21:10
  • no leer nada ... pero mirando defs de tipo probablemente debería usar createForm, nocreateFormInputVal
    xadm
    26 feb a las 21:22
0

Si la raíz del problema aquí es mutar o crear varios documentos a la vez, creo que se duplicó aquí:

https://stackoverflow.com/a/68930202/534056

Un par de cosas a tener en cuenta:

  • Elija un nombre para sus entradas personalizadas que no sea igual [type name] + Input. Esto es lo que Fauna usa para las operaciones CRUD generadas automáticamente, y si usted mismo define una, anulará la generada. Por ejemplo, dado el tipo Form, Fauna generará un tipo de entrada llamado FormInput, así que no lo use para uno personalizado.

  • Si desea pasar una matriz de datos como entrada, especifique el argumento como un tipo de Lista (colocado entre corchetes).

  • Si está actualizando algunos documentos, deberá pasar la identificación. La API GraphQL oculta algunos detalles sobre las referencias, por lo que en su UDF, deberá reconstruir la referencia a partir de una ID.