Data persistence
- Why do data persistence?
- Because it is not persistent, the data is stored in memory and is lost when refreshed
- In this way, the data of different pages can be unified throughout the project
- How to do?
- Use custom Hooks in conjunction with Localstorage
Persistent TAB data
1. Encapsulate addTag into useTag
const addTag=() = >{
const tagName = window.prompt('The name of the new label is');
if(tagName ! = =null&& tagName ! = =' '){
setTags([...tags,{id:createId(),name:tagName}])
}
};
Copy the code
2. When to put tags into localStorage? UseEffect to help you out
- Whenever the tags change, they are put into localStorage
- LocalStoarge can only store strings, so use
JSON.stringify
- Use a dependency for
[tags]
The useEffect
useEffect(() = >{ console.log('tags change') console.log(tags) window.localStorage.setItem('tags'.JSON.stringify(tags)) },[tags]) // Execute when dependency changes Copy the code
- Use a dependency for
- Add a useEffect to make the dependency
[]
- []: executes when the component is mounted, executes only once on mount, and then no longer executes
useEffect(() = >{ console.log('after mount') let localTags = JSON.parse(window.localStorage.getItem('tags') | |'[]') setTags(localTags) },[])// When the component is mounted, it is executed only once on mount and then no longer executed Copy the code
- What happens if you add a tag to two useeffects together?
- Print after mount first: depends on the useE of []
- Print tags change: useEffect dependent on [tags]
- Print [] : tags from un______ to []
- Print tags change: useEffect dependent on [tags]
- Print the newly added tags object: [] becomes the new object
- The first print [] is redundant, and the first print [] is not needed.
- Declare a ref, each time useEffect increments by 1,
- Equal to 1 means first render, first render does nothing.
- UseEffect is executed only when ref is greater than 1
- Encapsulate as a hook, useUpdate. I’m done with that extra set
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]) // Tags must be immutable. Each change is a new object, executed when tags change
}
export {useUpdate}
Copy the code
- So the useTags became
// Execute mount once and then no longer
useEffect(() = >{
let localTags = JSON.parse(window.localStorage.getItem('tags') | |'[]')
// If the length is 0, it is null, push default
if(localTags.length ===0){
localTags = [
{id:createId(), name:'clothes'},
{id:createId(), name:'food'},
{id:createId(), name:'live'},
{id:createId(), name:'row'}}]// Read localStoarge tags, then setTags
setTags(localTags)
},[])// When the component is mounted, it is executed only once on mount and then no longer executed
// Execute this when updating
useUpdate(() = >{
// console.log('set')
window.localStorage.setItem('tags'.JSON.stringify(tags))
},tags)
Copy the code
3. Note tags. TSX execution times
- Enter the TAB page
tags do it
It will execute it twice, the first time tags fromundeined
to[]
And the second[]
To the initialization value
function Tags() {
const {tags,addTag} = useTags()
console.log('tags do it')
return (
<Layout>
<TagList>
{tags.map(tag=>
<li key={tag.id}>
<Link to={'/tags/ '+tag.id} >
<span className="oneLine">{tag.name}</span>
<Icon name="right"></Icon>
</Link>
</li>
)}
</TagList>
<Center>
<Space/>
<Button onClick={addTag}>The new labels</Button>
<Space/>
</Center>
</Layout>
);
}
Copy the code
4. Process sorting
- Enter the TAB page
tags do it
It will execute it twice, the first time tags fromundeined
to[]
And the second[]
To the initialization value - Each time you switch pages, the component is remounted, i.e
useTags
In theuseEffect
It takes effect and sets the initial value- Go to the
localStorag
E, if it’s empty, push the initial value
- Go to the
- If the
tags
Update, and it will triggeruseUpdate
- Coexist in
localStorage
- Only if the set ref is greater than 1 (i.e. from [] to tags)
localStorage
- Coexist in
Persistent billing page data
1. Create userecord.tsx hooks
- AddRecord exposure records
import {useEffect, useState} from "react";
import {useUpdate} from "./useUpdate";
// The type of new record
type newRecordItem = {
tagIds:number[].note:string.category:"+" | The '-'.amount:number,}export type RecordItem = newRecordItem & {
createdAt:string //ISO 8601
}
const useRecords =() = >{
const [records,setRecords] = useState<RecordItem[]>([])
useEffect(() = >{
setRecords(JSON.parse(window.localStorage.getItem('records') | |'[]'))
},[])// Mount
useUpdate(() = >{
window.localStorage.setItem('records'.JSON.stringify(records))
},records)
const addRecord=(newRecord:newRecordItem) = >{
if(newRecord.amount <=0){
alert('Please enter the correct amount')
return false
}
if(newRecord.tagIds.length === 0){
alert('Please select label')
return false
}
constrecord = {... newRecord,createdAt: (new Date()).toISOString()}
setRecords([...records,record])
return true
}
return {records, addRecord}
}
export {useRecords}
Copy the code
2. Click OK on the bookkeeping page to submit the record
const submit=() = >{
if(addRecord(selected)) {
alert('Saved successfully')
setSelected(defaultFormData)
}
}
Copy the code
<NumberpageSection value={selected.amount}
onChange={(amount) = >onChange({amount})}
onOk={submit}
/>
Copy the code
3. Logic for adding records
- On the first rendering, mount the component
localStorage
In the readingrecords
- In the Money component, enter the record and click OK to call
addRecord
- in
useRecord
In the hook,addRecord
In the wouldsetRecords
To updaterecord
, trigger the update - Let the Money component execute again, and the Money component can get a new one
records
the - At the same time,
useRecords
In the calluseUpdate
, rely onrecords
When the record changes, update the new records tolocalStorage