The code written below is from the functionality file, I was building a notes app and wanted to add a folder option too to categorize all the notes but while displaying the changing/adding notes to a folder I find that the folder_files
state is getting updated after caling the add case of handleFileAddition
function but when I re-call the function the state updation that was done on the previous call always gets replaced with the initialized value of it i.e. I am adding a checked property to all notes stored in noteList state so that I can check/uncheck them using this:-
{folder_files.map(note => {
return
<>
<label
htmlFor={`note-${note.id}`}
className='note'
style={{ display: 'block', position: 'relative' }}
>
{note.para}
<input
type="checkbox"
checked={note.checked}
name={`note-${note.id}`}
id={`note-${note.id}`}
onChange={(e)=> handleFileAddition({
type: "add",
val: {
id: note.id,
check: e.target.checked
}
})}
style={{
position: 'absolute',
right: 0,
backgroundColor: "inherit"
}}
/>
</label>
</>
}
)}
Also due to folder_files
not retaining the updated state it's making the input checkboxes not retain their check functionality.
Below is the whole functionality of folder part of my Notes App:
function useFunctionality() {
const initialArr = []; // INITIAL ARRAY BEING ASSIGNED TO REDUCER HOOK
// CHOOSING DISPLAY BETWEEN FILES & FOLDER
const [choices, setChoices] = useState({
files: true,
folder_files: false,
choice: false,
change: {
val: false,
id: '',
para: '',
files: []
}
});
// FOR HOLDING THE FOLDERS & THE FILE SUPPOSED TO BE STORED IN THEM
const [folders, dispatchFolders] = useReducer(reducerFolder, initialArr);
// STATE FOR HOVERING, RIGHT CONTAINER'S CHILDREN DISPLAY &
// NEW NOTE ADDITION FUNCTIONALITY
const [isChanging, setIsChanging] = useState({
hover: false,
r_empty: false,
add: false,
change: {
val: false,
inp: '',
txt:'',
id: null
}
});
// REDUCER HOOK FOR ADDITION, CHANGE & DELETION OF NOTES
const [noteList, dispatch] = useReducer(reducer, initialArr);
// FILES WITH THE CHECKED PROPERTY ADDED
const [folder_files, setFolderFiles] = useState([])
const inputRef = useRef(''); // REF FOR INPUT FIELD(FOR FILES & FOLDERS)
const textRef = useRef(''); // REF FOR TEXT AREA(FOR FILES ONLY)
let files;
// let vg;
// REPRESENTING CHANGE HERE UPDATED STATE IS GETTING SHOWN
useEffect(() => {
console.log(
folder_files,
choices.change,
folder_files.filter(file => file.checked)
)
}, [folder_files])
function idGenerator(notes) { // NOTE'S ID GENERATOR
const arr = [...notes];
const result = arr.length !== 0 ? arr[arr.length -1].id + 1 : 1
return result;
}
function paraGenerator(inp, txt) { // GENERATING NOTES ENTRY FOR DISPLAY
let para;
switch(true) {
case (inp && txt !== '' ):
para = inp.slice(0, 15);
break;
case ((inp || txt) !== '' ):
para = inp !== '' ? inp.slice(0, 15) : txt.slice(0, 15);
break;
default:
para = null;
break;
}
console.log(para, inp, txt)
return para;
}
// DISPLAYING FOLDER NAMES OR THE EDITABLE SIDE
function handleFolderDisplay(
save = false,
changer = false,
value
) {
if (changer) {
setIsChanging({ ...isChanging, r_empty: true });
setChoices({
...choices,
change: {
val: true,
id: value.id,
para: value.para,
files: [value.folder_files]
}
})
} else {
if (!save) {
const idFold = idGenerator(folders);
setIsChanging({ ...isChanging, r_empty: true });
setChoices({
...choices,
change: {
val: false,
id: idFold,
para: '',
files: []
}
})
} else {
setIsChanging({ ...isChanging, r_empty: false });
const para = paraGenerator(inputRef.current.value, '');
if (choices.change.val) {
setChoices({
...choices,
change: {
val: false,
id: '',
para: ''
}
});
dispatchFolders({
type: "change",
values: {
id: choices.change.id,
para: inputRef.current.value
}
})
} else {
dispatchFolders({
type: "add",
values: {
id: "fold" + choices.change.id,
para: para,
files: files
}
});
}
}
}
}
// THE PROBLEM CODE BLOCK
function handleFileAddition(obj{
let ff;
switch (obj.type) {
case "display":
setChoices({ ...choices, folder_files: obj.val })
break;
case "add":
console.log(folder_files, obj.val.check)
setFolderFiles(prevFolderFiles => prevFolderFiles.map(file => {
if (file.id === obj.val.id) {
console.log(
"got it",
folder_files,
file.checked,
obj.val.check
);
try {
return { ...file, checked: obj.val.check };
} catch {
console.log("Error")
}
} else {
console.log("gt", file)
return file;
}
}));
break;
case "save" :
setChoices({ ...choices, folder_files: obj.val })
if (choices.change.val) {
dispatchFolders({
type: "file_change",
id: choices.change.id,
files: folder_files.filter(file=> file.checked)
});
setFolderFiles(folder_files.map(file => {
return { ...file, checked: false }
}))
}
}
}
function handleFolderDeletion(taskId) {
dispatchFolders({ type: "delete", id: taskId });
}
function handleChoices(choiceVal = true, files = choices.files) {
choices.files === files
? null
: setIsChanging({ ...isChanging, r_empty: false });
setChoices(prevChoices => ({
...prevChoices,
files: files, // Directly set based on files argument
choice: choiceVal // Update choice accordingly
? !prevChoices.choice
: false,
}));
const arr = noteList.map(note => note.checked = false)
setFolderFiles(noteList.map(note => {
return { ...note, checked: false }
}))
}
return {
isChanging,
choices,
inputRef,
textRef,
noteList,
folders,
folder_files,
handleChanging,
dispatch,
handleEmptiness,
handleDeletion,
handleChoices,
handleFolderDisplay,
handleFolderDeletion,
handleFileAddition
}
}
I was expecting the files to display checked state of theirs but they were not displaying it because of the folder_files
retaining their initial state instead of updated state.
The code written below is from the functionality file, I was building a notes app and wanted to add a folder option too to categorize all the notes but while displaying the changing/adding notes to a folder I find that the folder_files
state is getting updated after caling the add case of handleFileAddition
function but when I re-call the function the state updation that was done on the previous call always gets replaced with the initialized value of it i.e. I am adding a checked property to all notes stored in noteList state so that I can check/uncheck them using this:-
{folder_files.map(note => {
return
<>
<label
htmlFor={`note-${note.id}`}
className='note'
style={{ display: 'block', position: 'relative' }}
>
{note.para}
<input
type="checkbox"
checked={note.checked}
name={`note-${note.id}`}
id={`note-${note.id}`}
onChange={(e)=> handleFileAddition({
type: "add",
val: {
id: note.id,
check: e.target.checked
}
})}
style={{
position: 'absolute',
right: 0,
backgroundColor: "inherit"
}}
/>
</label>
</>
}
)}
Also due to folder_files
not retaining the updated state it's making the input checkboxes not retain their check functionality.
Below is the whole functionality of folder part of my Notes App:
function useFunctionality() {
const initialArr = []; // INITIAL ARRAY BEING ASSIGNED TO REDUCER HOOK
// CHOOSING DISPLAY BETWEEN FILES & FOLDER
const [choices, setChoices] = useState({
files: true,
folder_files: false,
choice: false,
change: {
val: false,
id: '',
para: '',
files: []
}
});
// FOR HOLDING THE FOLDERS & THE FILE SUPPOSED TO BE STORED IN THEM
const [folders, dispatchFolders] = useReducer(reducerFolder, initialArr);
// STATE FOR HOVERING, RIGHT CONTAINER'S CHILDREN DISPLAY &
// NEW NOTE ADDITION FUNCTIONALITY
const [isChanging, setIsChanging] = useState({
hover: false,
r_empty: false,
add: false,
change: {
val: false,
inp: '',
txt:'',
id: null
}
});
// REDUCER HOOK FOR ADDITION, CHANGE & DELETION OF NOTES
const [noteList, dispatch] = useReducer(reducer, initialArr);
// FILES WITH THE CHECKED PROPERTY ADDED
const [folder_files, setFolderFiles] = useState([])
const inputRef = useRef(''); // REF FOR INPUT FIELD(FOR FILES & FOLDERS)
const textRef = useRef(''); // REF FOR TEXT AREA(FOR FILES ONLY)
let files;
// let vg;
// REPRESENTING CHANGE HERE UPDATED STATE IS GETTING SHOWN
useEffect(() => {
console.log(
folder_files,
choices.change,
folder_files.filter(file => file.checked)
)
}, [folder_files])
function idGenerator(notes) { // NOTE'S ID GENERATOR
const arr = [...notes];
const result = arr.length !== 0 ? arr[arr.length -1].id + 1 : 1
return result;
}
function paraGenerator(inp, txt) { // GENERATING NOTES ENTRY FOR DISPLAY
let para;
switch(true) {
case (inp && txt !== '' ):
para = inp.slice(0, 15);
break;
case ((inp || txt) !== '' ):
para = inp !== '' ? inp.slice(0, 15) : txt.slice(0, 15);
break;
default:
para = null;
break;
}
console.log(para, inp, txt)
return para;
}
// DISPLAYING FOLDER NAMES OR THE EDITABLE SIDE
function handleFolderDisplay(
save = false,
changer = false,
value
) {
if (changer) {
setIsChanging({ ...isChanging, r_empty: true });
setChoices({
...choices,
change: {
val: true,
id: value.id,
para: value.para,
files: [value.folder_files]
}
})
} else {
if (!save) {
const idFold = idGenerator(folders);
setIsChanging({ ...isChanging, r_empty: true });
setChoices({
...choices,
change: {
val: false,
id: idFold,
para: '',
files: []
}
})
} else {
setIsChanging({ ...isChanging, r_empty: false });
const para = paraGenerator(inputRef.current.value, '');
if (choices.change.val) {
setChoices({
...choices,
change: {
val: false,
id: '',
para: ''
}
});
dispatchFolders({
type: "change",
values: {
id: choices.change.id,
para: inputRef.current.value
}
})
} else {
dispatchFolders({
type: "add",
values: {
id: "fold" + choices.change.id,
para: para,
files: files
}
});
}
}
}
}
// THE PROBLEM CODE BLOCK
function handleFileAddition(obj{
let ff;
switch (obj.type) {
case "display":
setChoices({ ...choices, folder_files: obj.val })
break;
case "add":
console.log(folder_files, obj.val.check)
setFolderFiles(prevFolderFiles => prevFolderFiles.map(file => {
if (file.id === obj.val.id) {
console.log(
"got it",
folder_files,
file.checked,
obj.val.check
);
try {
return { ...file, checked: obj.val.check };
} catch {
console.log("Error")
}
} else {
console.log("gt", file)
return file;
}
}));
break;
case "save" :
setChoices({ ...choices, folder_files: obj.val })
if (choices.change.val) {
dispatchFolders({
type: "file_change",
id: choices.change.id,
files: folder_files.filter(file=> file.checked)
});
setFolderFiles(folder_files.map(file => {
return { ...file, checked: false }
}))
}
}
}
function handleFolderDeletion(taskId) {
dispatchFolders({ type: "delete", id: taskId });
}
function handleChoices(choiceVal = true, files = choices.files) {
choices.files === files
? null
: setIsChanging({ ...isChanging, r_empty: false });
setChoices(prevChoices => ({
...prevChoices,
files: files, // Directly set based on files argument
choice: choiceVal // Update choice accordingly
? !prevChoices.choice
: false,
}));
const arr = noteList.map(note => note.checked = false)
setFolderFiles(noteList.map(note => {
return { ...note, checked: false }
}))
}
return {
isChanging,
choices,
inputRef,
textRef,
noteList,
folders,
folder_files,
handleChanging,
dispatch,
handleEmptiness,
handleDeletion,
handleChoices,
handleFolderDisplay,
handleFolderDeletion,
handleFileAddition
}
}
I was expecting the files to display checked state of theirs but they were not displaying it because of the folder_files
retaining their initial state instead of updated state.
1 Answer
Reset to default 0I think you're missing the key prop in list rendering.
{folder_files.map(note=>{
return <Fragment key={note.id}> // provide key
<label htmlFor={`note-${note.id}`} className='note' style={{display: 'block', position : 'relative'}} >
{note.para}<input type="checkbox" checked={note.checked} name={`note-${note.id}`} id={`note-${note.id}`} onChange={(e)=> handleFileAddition({type : "add", val : {id : note.id, check : e.target.checked}})} style={{position : 'absolute', right: 0, backgroundColor : "inherit"}}/>
</label>
</Fragment>
})}