Good Morning.
Need help, i have the below script, the thing is the setState is not working, I think I’m missing something here? or Am i doing wrong. the “return” in the below is inside “.map” so i could display the 3 file in the array. Thanks
constructor(props) { super(props); this.state = { // fileName: ['SAMPLE DOCUMENT 1', 'SAMPLE DOCUMENT 2', 'SAMPLE DOCUMENT 3'], file: [ {fileName: 'SAMPLE DOCUMENT 1', id: 123456, hash: '9153BB2EFC17BF53218FA15C977EDCD3', fileStatus: 'PENDING APPROVAL', fileId: 'APFEX-9153BB2E-C6F90E', isViewed: 'false', activateButton: false}, {fileName: 'SAMPLE DOCUMENT 2', id: 124234, hash: '9153BB2EFC17BF53218JEFSFH77EDCD3', fileStatus: 'PENDING APPROVAL', fileId: 'APFEX-9153BB2E-C6KS0E', isViewed: 'false', activateButton: false}, {fileName: 'SAMPLE DOCUMENT 3', id: 134564, hash: '9153BBMSJFOWN562DW689FWS641WES63', fileStatus: 'PENDING APPROVAL', fileId: 'APFEX-9153BB2E-CSS9HG', isViewed: 'false', activateButton: false} ], }; } activatebutton = (key) => { const {activateButton} = key this.setState({ activateButton: true }, () => { }); } return ( {this.state.file.map(file => ( <TableRow className={this.state.classes.row} key={file.id} data-id={file.id}> <CustomTableCell align="left" className={classes.row}> <a id={`download-${file.id}`} // onClick={() => downloadFile({ transactionId, fileId, id, fileName })} onClick={() => this.activatebutton(file)} rel="noreferrer" style={{textDecoration:'none',color:'#126ebd',cursor:'pointer'}} // eslint-disable-next-line no-script-url href="javascript:void(0);" > {file.fileName} </a> </CustomTableCell> <TableRow/> )
Advertisement
Answer
I imagine you want to recreate the file array, just changing the activateButton
property of the clicked item to true
. To do this in React, you must clone the array, mapping all items to themselves, except the one that you clicked. This one you create from scratch, spreading all the old properties and setting activateButton
to true
. Here’s the code:
activatebutton = (file) => (event) => { event.preventDefault(); // prevents the link from reloading the page const { id } = file; this.setState((state) => { const list = state.file; const newList = list.map((item) => item.id === id ? { ...item, activateButton: true } : item ); return { file: newList }; }); };
Comments:
activatebutton = (file) => (event) => {
We want activatebutton
to be a second order function, which receives the clicked item and then the event. Even better would be to pass only the id directly.
this.setState((state) => { … })
Whenever you want to update the state based on itself, use the functional setState. Pass a function whose parameter is the current state and the return is an update object. In this case, the file
property of state.
item.id === id ? { …item, activateButton: true } : item
This is short for:
if (item.id === id) { return Object.assign({}, item, {activateButton: true}) } else { return item }
I made a CodeSandbox Demo which even includes as the doubleClick event the toggling of the item.