I made three definitions in the Money-memory project: useUpdate, useRecords, useTags

1. UseUpdate: Use built-in Hook useEffect and useRef encapsulation

  • Purpose: To model componentDidUpdate() for class components
  • Only use useEffect to simulate componentDidUpdate() will lead to data from scratch will trigger FN, use useRef, before triggering FN add a judgment condition
import {useEffect, useRef} from 'react';

const useUpdate = (fn: () => void, dependency: any[]) = > {
  const count = useRef(0);
  useEffect(() = > {
    count.current += 1;
  });

  useEffect(() = > {
    if (count.current > 1) {
      fn();
    }
  }, [fn, dependency]);
};
export {useUpdate};
Copy the code

2. UseRecords: Encapsulate built-in hooks (useEffect, useRef) and custom hooks (useUpdate)

  • Purpose: Get and add billing page data, including labels, notes, income or expenditure, amount, and billing time, using an object to store this data
import {useEffect, useState} from 'react';
import {useUpdate} from './useUpdate';

// Declare the data type
type RecordItem = {
  tagIds: number[];
  note: string;
  category: '+' | The '-';
  amount: number;
  createAt: string; // ISO 8601
}
// Declare the type, excluding createAt
type NewRecordItem = Omit<RecordItem, 'createAt'>

export const useRecords = () = > {
  const [records, setRecords] = useState<RecordItem[]>([]);
  ComponentDidMount = componentDidMount = componentDidMount = componentDidMount
  useEffect(() = > {
    setRecords(JSON.parse(window.localStorage.getItem('records') | |'[]')); } []);// Simulate componentDidUpdate, write data to localStorage after updating records
  useUpdate(() = > {
    window.localStorage.setItem('records'.JSON.stringify(records));
  }, records);
  // The user completes an billing operation to add new data to records
  const addRecord = (newRecord: NewRecordItem) = > {
    if (newRecord.amount <= 0) {
      alert('Please enter amount');
      return false;
    }
    if (newRecord.tagIds.length <= 0) {
      alert('Please select at least one label');
      return false;
    }
    constrecord = {... newRecord,createAt: (new Date()).toISOString()};
    setRecords([...records, record]);
    return true;
  };
  return {
    records,
    addRecord
  };
};
Copy the code

3. UseTags: use built-in hooks (useEffect, useRef), custom hooks (useUpdate), and createId

  • Usage: Used to create a label and obtain the created label, including a unique ID, and a label name, stored in localStorage

createId.tsx

// Store the ID to localStorage for unified management of ids to avoid duplication
let id = parseInt(window.localStorage.getItem('idMax') | |'0');
const createId = (): number= > {
  id += 1;
  window.localStorage.setItem('idMax'.JSON.stringify(id));
  return id;
};
export {createId};
Copy the code

useTags.tsx

import {useEffect, useState} from 'react';
import {createId} from 'lib/createId';
import {useUpdate} from './useUpdate';
// Declare the tag attribute type
type Tag = {
  id: number;
  name: string
}
const useTags = () = > {
  const [tags, setTags] = useState<Tag[]>([]);
  useEffect(() = > {
    let localTags = JSON.parse(window.localStorage.getItem('tags') | |'[]');
    // Set the default label
    if(localTags.length === 0){
      localTags = [
        {id: createId(), name: 'clothes'},
        {id: createId(), name: 'food'},
        {id: createId(), name: 'live'},
        {id: createId(), name: 'row'}]; } setTags(localTags); } []);// When tags are updated, they are saved to localStorage
  useUpdate(() = >{
    window.localStorage.setItem('tags'.JSON.stringify(tags));
  }, tags)
  // Get the tag by id
  const findTag = (id: number) = > tags.filter(tag= > tag.id === id)[0];
  // Get the index of the current tag in tag group tags by id
  const findTagIndex = (id: number) = > {
    let result = -1;
    for (let i = 0; i < tags.length; i++) {
      if (tags[i].id === id) {
        result = i;
        break; }}return result;
  };
  // update the tag name
  const updateTag = (id: number, name: string) = > {
    setTags(tags.map(tag= > tag.id === id ? {id, name} : tag));
  };
  // Delete tags by id
  const deleteTag = (id: number) = > {
    setTags(tags.filter(tag= >tag.id ! == id)); };// Add a label. The label name cannot be empty
  const addTag = () = > {
    const tagName = window.prompt('Please enter a label name');
    if(tagName ! = =null&& tagName ! = =' ') {
      setTags([...tags, {id: createId(), name: tagName}]); }};// Get the label name by id
  const getName = (id: number) = > {
    const tag = tags.filter(t= > t.id === id)[0];
    return tag ? tag.name : ' ';
  }
  // External exposed interface
  return {
    tags,
    setTags,
    findTag,
    updateTag,
    findTagIndex,
    deleteTag,
    addTag,
    getName
  };
};

export {useTags};

Copy the code