Skip to content
Advertisement

How to make modal re-render when array is updated

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" class="btn btn-primary mt-5 center-block" data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={()=>{setPossibleFiles(files)}}>
            Plot
        </button>

        <div class="modal fade" id="exampleModal" aria-labelledby="exampleModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">Families Choosen</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <table class="table table-hover">
                    <thead>
                    <tr>
                        <th>File</th>
                    </tr>
                    </thead>

                    <tbody>
                        {mapSelectedFiles()}
                    </tbody>
                </table>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
            </div>
        </div>
        </div>
    </div>
);

}

Advertisement

Answer

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);
}
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement