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