hasura / ra-data-hasura

react-admin data provider for Hasura GraphQL Engine

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Define custom method in dataProvider

techpet opened this issue · comments

I am using buildHasuraProvider to construct my dataProvider inside the useEffect method:

const createApolloClient = async (token) => {
  return new ApolloClient({
    uri: "http://localhost:8080/v1/graphql",
    cache: new InMemoryCache(),
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });
};

const App = () => {
  const [dataProvider, setDataProvider] = React.useState({});
  const [isAuthenticated, setIsAuthenticated] = useState(null);

  React.useEffect(async () => {
    const buildDataProvider = async () => {
      const token = auth.getJWTToken();

      const apolloClient = await createApolloClient(token);


      const dataProvider = await buildHasuraProvider({
        client: apolloClient,
      })

      /* Custom dataProvider with createMany method

      const myDataProvider = {
      ...dataProvider,
      createMany: (resource, params) => {
        console.log("updated "+resource+" with "+params)
      }
    }

    console.log(myDataProvider);

   */



      setDataProvider(() => dataProvider);

    };

//...

The above code used to define myDataProvider (commented code) in order to add a createMany method in the dataProvider does not work as it does not return an extended dataProvider but rather an object with only a createMany method.

What is the appropriate way to extend the dataProvider with a new custom method. Could you provide an example?

For anyone interested, I had to override all dataProvider methods in order to add the additional custom method and make it work:

export default buildHasuraProvider().then((dataProviderHasura) => ({
  getList: (resource, params) => dataProviderHasura(GET_LIST, resource, params),
  getOne: (resource, params) => dataProviderHasura(GET_ONE, resource, params),
  getMany: (resource, params) => dataProviderHasura(GET_MANY, resource, params),
  getManyReference: (resource, params) => dataProviderHasura(GET_MANY_REFERENCE, resource, params),
  update: (resource, params) => dataProviderHasura(UPDATE, resource, params),
  updateMany: (resource, params) => dataProviderHasura(UPDATE_MANY, resource, params),
  create: (resource, params) => dataProviderHasura(CREATE, resource, params),
  delete: (resource, params) => dataProviderHasura(DELETE, resource, params),
  deleteMany: (resource, params) => dataProviderHasura(DELETE_MANY, resource, params),
  createMany: (resource, params) => {
       // CUSTOM METHOD DEFINITION HERE
    }
}));

For anyone interested, I had to override all dataProvider methods in order to add the additional custom method and make it work:

export default buildHasuraProvider().then((dataProviderHasura) => ({
  getList: (resource, params) => dataProviderHasura(GET_LIST, resource, params),
  getOne: (resource, params) => dataProviderHasura(GET_ONE, resource, params),
  getMany: (resource, params) => dataProviderHasura(GET_MANY, resource, params),
  getManyReference: (resource, params) => dataProviderHasura(GET_MANY_REFERENCE, resource, params),
  update: (resource, params) => dataProviderHasura(UPDATE, resource, params),
  updateMany: (resource, params) => dataProviderHasura(UPDATE_MANY, resource, params),
  create: (resource, params) => dataProviderHasura(CREATE, resource, params),
  delete: (resource, params) => dataProviderHasura(DELETE, resource, params),
  deleteMany: (resource, params) => dataProviderHasura(DELETE_MANY, resource, params),
  createMany: (resource, params) => {
       // CUSTOM METHOD DEFINITION HERE
    }
}));

I am also having this exact same issue. Did you add these on to another component? Or did you add them on the App.js?

Can you provide me with the full example of this? I'll appreciate this a looooooot! @techpet

@createdbyken Sure! In this approach the items are just created one by one (simplest approach). A more efficient solution would be to utilize the corresponding resource bulk Mutation in the Hasura instance by creating a new custom mutation request that sends the data array as the value of the objects variable.

export default buildHasuraProvider().then((dataProviderHasura) => ({
  getList: (resource, params) => dataProviderHasura(GET_LIST, resource, params),
  getOne: (resource, params) => dataProviderHasura(GET_ONE, resource, params),
  getMany: (resource, params) => dataProviderHasura(GET_MANY, resource, params),
  getManyReference: (resource, params) =>
    dataProviderHasura(GET_MANY_REFERENCE, resource, params),
  update: (resource, params) => dataProviderHasura(UPDATE, resource, params),
  updateMany: (resource, params) =>
    dataProviderHasura(UPDATE_MANY, resource, params),
  create: (resource, params) => dataProviderHasura(CREATE, resource, params),
  
  delete: (resource, params) => dataProviderHasura(DELETE, resource, params),
  deleteMany: (resource, params) =>
    dataProviderHasura(DELETE_MANY, resource, params),
  createMany: (resource, params) => {
    let responseData = []
    for (let key in params.data){
      let data = {"data":params.data[key]}
      dataProviderHasura(CREATE, resource, data).then(response=>
           responseData.push(response.data)})
      }

    return {"data":responseData}
  },
}));