Search code examples
reactjsgoogle-chrome-extensionlocal-storagedry

How can I make syntax less repetitive (DRY)?


The object of this app is to allow input text and URLs to be saved to localStorage. It is working properly, however, there is a lot of repeat code.

For example, localStoredValues and URLStoredVAlues both getItem from localStorage. localStoredValues gets previous input values from localStorage whereas URLStoredVAlues gets previous URLs from localStorage.

updateLocalArray and updateURLArray use spread operator to iterate of previous values and store new values.

I would like to make the code more "DRY" and wanted suggestions.

/*global chrome*/

import {useState} from 'react';
import List from './components/List'
import { SaveBtn, DeleteBtn, DisplayBtn, TabBtn} from "./components/Buttons"


function App() {
  const [myLeads, setMyLeads] = useState([]);
  const [leadValue, setLeadValue] = useState({
    inputVal: "",
  });


  //these items are used for  the state of localStorage
  const [display, setDisplay] = useState(false);
  const localStoredValues = JSON.parse(
    localStorage.getItem("localValue") || "[]"
  )
  let updateLocalArray = [...localStoredValues, leadValue.inputVal]

  //this item is used for the state of localStorage for URLS
  const URLStoredVAlues = JSON.parse(localStorage.getItem("URLValue") || "[]")

  const tabBtn = () => {
     chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
       const url = tabs[0].url;
       setMyLeads((prev) => [...prev, url]);

       // update state of localStorage
       let updateURLArray = [...URLStoredVAlues, url];
       localStorage.setItem("URLValue", JSON.stringify(updateURLArray));
     }); 
    setDisplay(false)
  };

  //handles change of input value
  const handleChange = (event) => {
    const { name, value } = event.target;
    setLeadValue((prev) => {
      return {
        ...prev,
        [name]: value,
      };
    });
  };

  const saveBtn = () => {
    setMyLeads((prev) => [...prev, leadValue.inputVal]);
    setDisplay(false);

    // update state of localStorage
    localStorage.setItem("localValue", JSON.stringify(updateLocalArray))
  };

  

  const displayBtn = () => {
    setDisplay(true);
  };

  const deleteBtn = () => {
    window.localStorage.clear();
    setMyLeads([]);
  };

  const listItem = myLeads.map((led) => {
    return <List key={led} val={led} />;
  });

  //interates through localStorage items returns each as undordered list item
  const displayLocalItems = localStoredValues.map((item) => {
    return <List key={item} val={item} />;
  });

  const displayTabUrls = URLStoredVAlues.map((url) => {
    return <List key={url} val={url} />;
  });

  return (
    <main>
      <input
        name="inputVal"
        value={leadValue.inputVal}
        type="text"
        onChange={handleChange}
        required
      />

      <SaveBtn saveBtn={saveBtn} />
      <TabBtn tabBtn={tabBtn} />
      <DisplayBtn displayBtn={displayBtn} />
      <DeleteBtn deleteBtn={deleteBtn} />

      <ul>{listItem}</ul>

      {/* displays === true show localstorage items in unordered list 
          else hide localstorage items */}
      {display && (
        <ul>
          {displayLocalItems}
          {displayTabUrls}
        </ul>
      )}
    </main>
  );
}

export default App

Solution

  • Those keys could be declared as const and reused, instead of passing strings around:

    const LOCAL_VALUE = "localValue";
    const URL_VALUE = "URLValue";
    

    You could create a utility function that retrieves from local storage, returns the default array if missing, and parses the JSON:

    function getLocalValue(key) {
      return JSON.parse(localStorage.getItem(key) || "[]")
    };
    

    And then would use it instead of repeating the logic when retrieving "localValue" and "URLValue":

    const localStoredValues = getLocalValue(LOCAL_VALUE) 
    
    //this item is used for the state of localStorage for URLS
    const URLStoredVAlues = getLocalValue(URL_VALUE)
    

    Similarly, with the setter logic:

    function setLocalValue(key, value) {
      localStorage.setItem(key, JSON.stringify(value))
    }
    

    and then use it:

    // update state of localStorage
    let updateURLArray = [...URLStoredVAlues, url];
    setLocalValue(URL_VALUE, updateURLArray);
    
    
    // update state of localStorage
    setLocalValue(LOCAL_VALUE, updateLocalArray)