React Redux components with REST Endpoints and reusable components

Viewed 140

I am working on a React-Redux (with hooks) project, where I have a baseURL with different endpoints. For example

  • baseURL = "https://jsonplaceholder.typicode.com"
  • endpoints = "/posts", "/comments", "/albums"

I have 2 questions:

  1. Where to keep the endpoint in the react (comments) component (for example: "/comments")
  2. How to reuse the code for other components like posts and albums because the accessToken code and headers are same for all of them.

const accessToken = localStorage.getItem("accessToken");
    Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
    var bodyParameters = {
      page: 1,
      pageSize: 50,
    };

    return fetch(baseURL, {
      credentials: "include",
      method: "post",
      body: JSON.stringify(bodyParameters),
      headers: {
        Authorization: `JWT ${accessToken}`,
        "X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
        "cache-control": "no-cache",
        pragma: "no-cache",
      },

My redux action looks like this

export const readList = () => {
  return (dispatch) => {
    const accessToken = localStorage.getItem("accessToken");
    Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
    var bodyParameters = {
      page: 1,
      pageSize: 50,
    };

    return fetch(baseURL, {
      credentials: "include",
      method: "post",
      body: JSON.stringify(bodyParameters),
      headers: {
        Authorization: `JWT ${accessToken}`,
        "X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
        "cache-control": "no-cache",
        pragma: "no-cache",
      },
    })
      .then((response) => {
        return response.json();
      })
      .then((data) =>
        dispatch(
          {
            type: READ_LIST,
            payload: data,
          },
          console.log("Actions: ", data)
        )
      )
      .catch((error) => {
        console.log(error.response);
        throw error;
      });
  };
};

and the react component looks like this

import "./styles.css";
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { readList } from "./redux/actionCreators";
import { FormattedMessage } from "react-intl";
import { DataGrid } from "@material-ui/data-grid";

export default function App() {
  const dispatch = useDispatch();
  const historyList = useSelector(
    (state) => state.reducers.commentsData.data || []
  );

  useEffect(() => {
    dispatch(readList());
  }, [dispatch]);

  let rows = historyList.map((obj, index) => {
    return (rows = {
      id: index,
      "User ID": obj.userId,
      Title: obj.title,
      Body: obj.body
    });
  });

  const columns = [
    {
      field: "User ID",
      flex: 1,
      renderHeader: () => <FormattedMessage id={"userId"} />
    },
    {
      field: "Title",
      flex: 1,
      value: "dropdown",
      renderHeader: () => <FormattedMessage id={"title"} />
    },
    {
      field: "Body",
      flex: 1,
      type: "date",
      renderHeader: () => <FormattedMessage id={"body"} />
    }
  ];

  return (
    <div className={"uhes-pageWrapper"}>
      <h1 className="uhes-pageHeader">
        <FormattedMessage id="History" />
      </h1>
      <div style={{ height: "90%", width: "100%" }}>
        <DataGrid
          pageSize={50}
          rowsPerPageOptions={[50, 100, 150]}
          rows={rows}
          columns={columns}
        />
      </div>
    </div>
  );
}

Thank you!

1 Answers

The ideas to reuse api configs, includes baseURL, accesstoken,... somethings like this

  1. You will have a service called apiService: where you manage your fetch configs like headers, and you can also add your token in there. apiService will return REST functions: POST/PUT/GET/DELETE/PATCH with available header configurations

Example:

const customFetch = (path, options) => {
    const accessToken = localStorage.getItem("accessToken");
    Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
    var bodyParameters = {
        page: 1,
        pageSize: 50
    };

    return fetch(`${baseURL}/${path}`, {
        credentials: "include",
        headers: {
            Authorization: `JWT ${accessToken}`,
            "X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
            "cache-control": "no-cache",
            pragma: "no-cache"
        },
        ...options
    });
};

const post = (path, bodyParameters) =>
    customFetch(path, {
        method: "POST",
        body: JSON.stringify(bodyParameters)
    });

const get = (path, queries) =>
    customFetch(queries ? `${path}/${qs.stringify(queries)}` : path, {
        method: "GET"
    });

const put = (path, bodyParameters) =>
    customFetch(path, {
        method: "PUT"
        body: JSON.stringify(bodyParameters)
    });

const delete = (path, id) =>
    customFetch(`${path}/${id}`, {
        method: "DELETE"
    });
  1. After that you can custom your readList with dynamic endpoint like this

    const readList = (resource) => apiService.get(resource) 
    
    readList('/posts');
    readList('/comments');
    readList('/albums');
    
Related