Skip to content

08 Mutations

JP Barbosa edited this page Apr 18, 2021 · 3 revisions

Mutations (Create, Update, Remove)

Components

Components

Create useMutation Hook

code ./src/hooks/useMutation.ts
import axios from 'axios';
import { Record } from '../interfaces/RecordEntities';

export type Action<T> = (record: T) => Promise<void>;

export const useMutation = <T extends Record>(path: string) => {
  const url = `${process.env.REACT_APP_API}/${path}`;

  const create: Action<T> = async (record: T) => {
    await axios.post(url, record);
  };

  const update: Action<T> = async (record: T) => {
    await axios.put(`${url}/${record.id}`, record);
  };

  const remove: Action<T> = async (record: T) => {
    await axios.delete(`${url}/${record.id}`);
  };

  return {
    create,
    update,
    remove,
  };
};

Pass apiPath to RecordMutations in RecordIndex

code ./src/pages/Record/index.tsx
...

export const RecordIndex = <...>(...) => {
  ...

  return (
    <div className="page">
      <div className="content">
        ...
        <RecordMutations<T>
          ...
          apiPath={apiPath}
        />
      </div>
    </div>
  );
};

Add apiPath to RecordMutationsProps

code ./src/interfaces/PagesProps.ts
export interface RecordMutationsProps<T> {
  ...
  apiPath: string;
}

Add apiPath and actions to RecordMutations

code ./src/pages/Record/Mutations.tsx
...
import { useMutation } from '../../hooks/useMutation';

export const RecordMutations = <T extends Record>({
  ...
  apiPath,
}: RecordMutationsProps<T>) => {
  const { create, update, remove } = useMutation<T>(apiPath);

  return (
    <div className="mutations">
      {activeRecord.id ? (
        <RecordEdit<T>
          ...
          update={update}
          remove={remove}
        />
      ) : (
        <RecordNew<T>
          ...
          create={create}
        />
      )}
    </div>
  );
};

Add actions to RecordNewProps, RecordEditProps and RecordFormProps

code ./src/interfaces/PagesProps.ts
import { Action } from '../hooks/useMutation';

...

export interface RecordNewProps<T> {
  ...
  create: Action<T>;
}

export interface RecordEditProps<T> {
  ...
  update: Action<T>;
  remove: Action<T>;
}

export interface RecordFormProps<T> {
  ...
  submitAction: Action<T>;
}

...

Add create action to RecordNew

code ./src/pages/Record/New.tsx
...

export const RecordNew = <T extends Record>({
  ...
  create,
}: RecordNewProps<T>) => {
  return (
    ...
      <RecordForm
        ...
        submitAction={create}
      />
    ...
  );
};

Add updade and remove to RecordEdit

code ./src/pages/Record/Edit.tsx
...

export const RecordEdit = <T extends Record>({
  ...
  update,
  remove,
}: RecordNewProps<T>) => {
  return (
    <div className="edit">
      <button className="bt-remove" onClick={() => remove(activeRecord)}>
        Remove
      </button>
      <h2>Edit</h2>
      <RecordForm
        ...
        submitAction={update}
      />
    </div>
  );
};

Add submitAction to RecordForm

code ./src/pages/Record/Form.tsx
...

export const RecordForm = <T extends Record>({
  ...
  submitAction,
}: RecordFormProps<T>) => {
  const { ... , handleSubmit } = useForm<T>(
    ...
    submitAction
  );

  ...

  return (
    <div>
      <form onSubmit={handleSubmit}>
        ...
      </form>
    </div>
  );
};

Add handleSubmit to useForm hook

code ./src/hooks/useForm.ts
...
import { Action } from './useMutation';

...

export const useForm = <T>(..., handleAction: Action<T>) => {
  ...

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
    event.preventDefault();
    handleAction(formState);
  };

  return { ..., handleSubmit };
};

Result

Result

Commit

git add .
git commit -m "Mutations"

Next step: Fetch Callback