Home > Blockchain >  Element not updating when changing State Array boolean
Element not updating when changing State Array boolean

Time:07-12

Okay so I have the following array in _app.js:

this.state = {
    assets: [
        { id: uuidv4(), selected: false, text: 'Sorte', url: 'https://images-cdn.bridgemanimages.com/api/1.0/image/600wm.XXX.42211270.7055475/7208045.jpg', title: 'Drumhop Second Time', description: 'Power & Strife - The disuasion of the middle class', keywords: 'lolly;pop;ping;bop' },
        { id: uuidv4(), selected: false, text: 'optical_dillusion2322.jpg', url: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfarL6oOr3NRwYXEJHK7AWPYzimZimjrjlh0Vm5LYOrHCoKBKmj0MAkjK2pJQBRmlkJLQ&usqp=CAU', title: 'Optimal Popsical', description: 'Optical Illusions for the masses', keywords: 'optical;illusion' },
    ],
}

This gets passed down to the pagination and displayed in Asset.jsx:

export default function Asset(props) {

    const {
        asset,
        index,
        onHandleAssetIDChange,
        onHandleAddAssetToWithdrawList,
    } = props

    return(
        <div className={`rounded overflow-hidden shadow-lg ${asset.selected === true ? "border-4 border-primary" : false}`} >
            <div className="flex flex-col relative group">
                <img
                    className="w-full h-48 object-cover"
                    src={asset.url}
                    alt={asset.description}
                />
                <div className="absolute top-2 left-2 text-primary flex gap-2 bg-white/70 px-3 py-2 rounded group-hover:opacity-100 opacity-0 duration-100">
                    <FiEdit className='text-2xl cursor-pointer' onClick={(e) => {
                        onHandleAssetIDChange(asset.id)
                    }}/>
                    <BsCircle className='text-2xl cursor-pointer' onClick={(e) => {
                        onHandleAddAssetToWithdrawList(asset.id)
                    }}/>
                </div>
                <div className="flex-1 p-6">
                    <div className="">{asset.text}</div>
                </div>
            </div>
        </div>
    )
}

As you see from the above, I have the line ${asset.selected === true ? "border-4 border-primary" : false} which updates the border if the asset has the selected flag set to true.

However for some reason, when I change the state of a 'selected' in the assets list, it doesnt update the element with the border. Here's how I change the state:

handleAddAssetToWithdrawList(assetID) {
    const newAssets = this.state['assets'].map(prevState =>
        prevState.id === assetID ? { ...prevState, selected: !prevState.selected } : prevState
    );
    this.setState({ assets : newAssets });
    console.log(newAssets)
}

So If I click the checkbox, change the page in the pagination, then go back to the original page, the border does change. But only once I move around the pagination and come back. It doesnt update straight away.

What am I doing wrong?

CodePudding user response:

You can use your condition before constructing your className, this way it will be re-rendered once the state changes. For having a cleaner JSX, you can assign the common part of your class to some variable. Something like this:

const borderlessClass = "rounded overflow-hidden shadow-lg"

<div className={asset.selected === true ? `${borderlessClass} border-4 border-primary` : borderlessClass} >

CodePudding user response:

It is necessary to add your dependency to dependency array of useEffect:

useEffect(() => { console.log(assets) }, [assets])

As this beautiful answer says:

Also, the main issue here is not just the asynchronous nature but the fact that state values are used by functions based on their current closures, and state updates will reflect in the next re-render by which the existing closures are not affected, but new ones are created.

  • Related