关于useState赋值后,导致页面重新渲染,数据初始化的问题
来源:8-5 在 App 中集成文件操作

张彬
2022-03-29
老师您好,我这发现,只要一更新编辑器里的内容,就会触发重新渲染,这个问题一直纠结中,因为一重新渲染,files就初始化了,以下是我的代码,麻烦老师给我看看
说明:我的相关组件版本:
“electron”: “^17.1.2”,
“react-simplemde-editor”: “^5.0.2”,
import React, { useState,useCallback,useMemo } from "react";
import { v4 as uuidv4 } from 'uuid';
import {flattenArr,objToArr} from '@/utils/helper'
import fileHelper from '@/utils/fileHelper'
import SimpleMDE from "react-simplemde-editor";
import 'bootstrap/dist/css/bootstrap.min.css'
import "easymde/dist/easymde.min.css";
import './App.scss';
import FileSearch from './components/FileSearch';
import FileList from './components/FileList';
import BottomBtn from '@/components/BottomBtn';
import TabList from '@/components/TabList';
import { faPlus,faFileImport,faSave } from '@fortawesome/free-solid-svg-icons'
import defaultFiles from './mock/defaultFiles';
const fs = window.require('fs')
const {join} = window.require('path')
const remote = window.require('@electron/remote')
function App() {
const [files,setFiles] = useState(flattenArr(defaultFiles))
const [activeFileID,setActiveFileID]=useState('')
const [openedFileIDs,setOpenedFileIDs]=useState([])
const [unsavedFileIDs,setUnsavedFileIDs]=useState([])
const [searchedFiles,setSearchedFiles]=useState([])
const filesArr=objToArr(files);
const activeFile = files[activeFileID]
const fileListArr =(searchedFiles.length>0)?searchedFiles:filesArr;
const savedLocation=remote.app.getPath('documents')
const openedFiles = openedFileIDs.map(openID=>{
return files[openID]
})
//SimpleMDE config
const autofocusNoSpellcheckerOptions = useMemo(() => {
return {
autofocus: true,
spellChecker: false,
minHeight:'515px'
};
}, []);
const fileClick=(fileID)=>{
//if openedFiles don't have the current ID
//set current active id;
setActiveFileID(fileID)
console.log(files)
//add new fileID to openedFiles
if(!openedFileIDs.includes(fileID)){
setOpenedFileIDs([...openedFileIDs,fileID])
}
}
const tabClick=(fileID)=>{
//set current active id;
setActiveFileID(fileID)
}
const tabClose=fileID=>{
//remove current id from openedFileIDs
let idx=openedFileIDs.indexOf(fileID)
const tabsWithout=openedFileIDs.filter(id=>id!==fileID)
setOpenedFileIDs(tabsWithout)
//set the active to the first opened tab if still tabs left
if(fileID===activeFileID){
if(tabsWithout.length>0){
setActiveFileID(tabsWithout[idx>0?idx-1:0])
}else{
setActiveFileID('')
}
}
}
const fileChange=useCallback((fileID,value)=>{
// loop through file array to update
console.log(fileID,files,files[fileID])
const newFile={...files[fileID],body:value}
setFiles({...files,[fileID]:newFile})
// update unsaveIDs
if(!unsavedFileIDs.includes(fileID)){
setUnsavedFileIDs([...unsavedFileIDs,fileID])
}
},[])
const deleteFile=(fileID)=>{
//filter out the current file id
delete files[fileID]
setFiles(files)
//close the tab if opened
tabClose(fileID)
}
const updateFileName=(fileID,title,isNew)=>{
const modifiedFile={...files[fileID],title,isNew:false};
console.log(modifiedFile)
if(isNew){
fileHelper.writeFile(join(savedLocation,`${title}.md`),modifiedFile.body).then(res=>{
setFiles({...files,[fileID]:modifiedFile})
})
}else{
fileHelper.renameFile(join(savedLocation,`${files[fileID].title}.md`),join(savedLocation,`${title}.md`)).then(res=>{
setFiles({...files,[fileID]:modifiedFile})
})
}
console.log(files)
}
const fileSearch=(keyword)=>{
//filter out this new files based on the keyword
const newFiles=filesArr.filter(file=>file.title.includes(keyword));
setSearchedFiles(newFiles)
}
const createNewFile=()=>{
const isEditFile=filesArr.find(file=>file.isNew)
if(!isEditFile){
const newId=uuidv4();
const newFiles={
...files,
[newId]:{
id:newId,
title:'',
body:'## 请输入 Markdown',
createdAt:new Date().getTime(),
isNew:true
}
}
setFiles(newFiles)
}
}
const saveCurrentFile=()=>{
fileHelper.writeFile(join(savedLocation,`${activeFile.title}.md`),activeFile.body).then(res=>{
setUnsavedFileIDs(unsavedFileIDs.filter(id=>id!==activeFile.id))
})
}
return (
<div className="App container-fluid g-0">
<div className='row g-0'>
<div className='col-3 left-panel'>
<FileSearch title="我的云文档" onFileSearch={fileSearch}></FileSearch>
<FileList files={fileListArr} onFileClick={fileClick} onSaveEdit={updateFileName} onFileDelete={deleteFile}></FileList>
<div className='row g-0 button-group'>
<div className='col g-0'><BottomBtn text="新建" colorClass="btn-primary" icon={faPlus} onBtnClick={createNewFile}></BottomBtn></div>
<div className='col g-0'><BottomBtn text="导入" colorClass="btn-success" icon={faFileImport} onBtnClick={()=>{}}></BottomBtn></div>
</div>
</div>
<div className='col-9 right-panel'>
{!activeFile &&
<div className="start-page">选择或者创建新的 Markdown 文档 </div>
}
{activeFile && <>
<TabList files={openedFiles} activeId={activeFileID} unsaveIds={unsavedFileIDs} onTabClick={tabClick} onCloseTab={tabClose}></TabList>
<SimpleMDE key={activeFile&&activeFile.id} value={activeFile&&activeFile['body']} options={autofocusNoSpellcheckerOptions} onChange={(v)=>{fileChange(activeFile.id,v)}}></SimpleMDE>
<div className='col g-0'><BottomBtn text="保存" colorClass="btn-success" icon={faSave} onBtnClick={saveCurrentFile}></BottomBtn></div>
</>}
</div>
</div>
</div>
);
}
export default App;
写回答
1回答
-
张彬
提问者
2022-03-29
老师您好,是下面这段代码的问题
const fileChange=useCallback((fileID,value)=>{ // loop through file array to update console.log(fileID,files,files[fileID]) const newFile={...files[fileID],body:value} setFiles({...files,[fileID]:newFile}) // update unsaveIDs if(!unsavedFileIDs.includes(fileID)){ setUnsavedFileIDs([...unsavedFileIDs,fileID]) } },[]) 但之前改这段代码,也是为了解决输入会引起重新渲染,拿不到activeID,但神奇的是,现在把这个代码改回去,又好了,实在有点想不通00
相似问题