I'm pretty sure this is a simple issue but its stumped me.
Run down: Essentially I have a list of files displayed on a table as table cells. When one is selected it becomes highlighted and is added to an array, I also can remove an item from my array by clicking again on it. Then Once I hit a button the array is added to a state using setState() where you have a modal with another table that contains your selected files and a button to remove them from the table/array.
Issue: My problem is that after I render my modal for the first time it refuses to update. I've tried using a useeffect and such but nothing has worked so far. I can get it to "work" by just reloading the entire page but thats obviously not ideal. So any suggestions would be appreciated. Also below on the code you can assume that file is just an array of objects aka files with a couple characteristics.
Code:
export default function ConfirmBtn({files}){
const [possibleFiles,setPossibleFiles] = useState([])
const removeFile = (fileToRemove) =>{
for(let i = 0; i < files.length;i ){
if(files[i] == fileToRemove){
possibleFiles.splice(i,1)
}
}
}
const mapSelectedFiles = () => {
return(
possibleFiles.map(file=>(
getFiles(file)
)))
}
const getFiles = (file) =>{
return(
<tr key = {file.id} >
<td>{file.cal_id file.e_id}</td>
<td><button id = {file.f_name} onClick={()=>{removeFile(file)}}>Remove</button></td>
</tr>
)
}
return(
<div className='modealBackgroud'>
<button type="button" data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={()=>{setPossibleFiles(files)}}>
Plot
</button>
<div id="exampleModal" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div >
<div >
<div >
<h5 id="exampleModalLabel">Families Choosen</h5>
<button type="button" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div >
<table >
<thead>
<tr>
<th>File</th>
</tr>
</thead>
<tbody>
{mapSelectedFiles()}
</tbody>
</table>
</div>
<div >
<button type="button" data-bs-dismiss="modal">Close</button>
<button type="button" >Save changes</button>
</div>
</div>
</div>
</div>
</div>
);
}
CodePudding user response:
What's wrong in your code is that you are updating your state directly and react don't update states directly if it is referenced type, which an array is. So what you have to do is use the setPossibleFiles([...newArray] to update the state.
Note: Don't update the state directly always use setState method to update the state. Changing state directly is a bad pattern and your code might not work properly.
const [possibleFiles,setPossibleFiles] = useState([])
const removeFile = (fileToRemove) =>{
const newPossibleFilesState = [...possibleFiles];
for(let i = 0; i < newPossibleFilesState.length;i ){
if(newPossibleFilesState[i] === fileToRemove){
newPossibleFilesState.splice(i,1)
}
}
setPossibleFiles(newPossibleFilesState);
}
CodePudding user response:
it's cleaner if you use filter
to remove the item like this
const [possibleFiles,setPossibleFiles] = useState([])
const removeFile = (fileToRemove) =>{
setPossibleFiles(files => files.filter(file => file.id !== fileToRemove.id));
}
CodePudding user response:
I think you should create a temporary variable to store the remaining files (while deleting the selected file). And call setPossibleFiles().
const removeFile = (fileToRemove) =>{
let newFiles = possibleFiles.filter(file => file.id !== fileToRemove.id);
setPossibleFiles(newFiles)
}