Summary: I have a component that contains an Antd Table
component. The Antd Table component is created initially based on the original userData
that is generated using a fetch
request. The data is loaded initially and set using setState(fetchedData)
calling render()
to display appropriately. This works.
Using the NiceModal
library, I present a new modal component and pass in a doCompelte
closure that will then setstate
again with the updated data. From here, the render()
method is called again. I log the updated userData
in the render()
method before the data is loaded and it shows the data is updated and it confirms that render()
is called with the new data. But, the visual display never actually loads on the screen.
At this point, I stopped taking user input from the Modal and tried giving it direct values, as shown in EditModal.jsx. This still doesn’t work and I’m unsure of why.
Question: Why is my component render()
method called, new data printed correctly, but the React Antd Table is not loading the new data?
Note: I did try creating a local variable inside the render()
method that accesses userData
at that given time but this also doesn’t update the table.
UPDATE 1: You can see that the first name is "Mrs."
then it gets hardcode changed to "GPRLEJAF"
inside the showEditModal()
function which now does NOT show a modal, it just changes the value and sets the state.
You’ll see that the re-rendering shows the update in the console but the table is never updated.
UserList.jsx
import React, { useEffect } from 'react';
import NiceModal, { useModal } from '@ebay/nice-modal-react';
import { Button, Table } from 'antd';
import { EditOutlined } from '@ant-design/icons';
import AddCircle from '../../../node_modules/material-jsx-icons/dist/icons/add_circle';
import { useLocation } from 'react-router-dom';
import AddModal from './AddModal'
import EditModal from './EditModal'
import "./Table.css";
import 'bootstrap/dist/css/bootstrap.min.css';
import data from '../../mock';
function search() {
}
function withMyHook(Component) {
return function WrappedComponent(props) {
const myHookValue = useLocation();
return <Component {...props} myHookValue={myHookValue} />;
}
}
class UserList extends React.Component {
constructor(props) {
super(props);
this.state = {
userData: [],
}
}
self = this;
columns = [
{
title: 'First Name',
dataIndex: 'First_Name',
width: '10%',
align: 'center',
},
{
title: 'Last Name',
dataIndex: 'Last_Name',
width: '10%',
align: 'center',
},
{
title: 'Address',
dataIndex: 'Address',
width: '20%',
align: 'center',
},
{
title: 'Billed',
dataIndex: 'Billed',
width: '5%',
align: 'center',
},
{
title: 'Work Date',
dataIndex: 'Work_Date',
width: '12%',
align: 'center',
},
{
title: 'Last Modified Date',
dataIndex: 'Table_Date',
width: '12%',
align: 'center',
},
{
title: 'Notes',
dataIndex: 'Notes',
width: '32%',
align: 'center',
},
{
title: 'Actions',
width: '5%',
align: 'center',
dataIndex: 'taco',
render: (_, value) => <Button type="link" icon={<EditOutlined />} onClick={() => this.showEditModal(value)}/>
},
];
showEditModal(value) {
/*
var index = this.userData.findIndex(item => item == value);
NiceModal.show(EditModal, { data: value, onEdit: (updatedUser) => {
this.userData[index] = updatedUser; // Update current user with updated data
this.setState([...this.userData]); // Re-Render with new data
}});
*/
this.userData[0].First_Name = "Random Name";
this.setState([this.userData]);
};
iconStyles = {
width: '25px',
fill: '#ffffff',
justifyContent: 'center',
alignItems: 'center',
float: 'left',
marginRight: '5px',
};
componentDidMount() {
console.log("Updating");
const token = this.props.myHookValue.state['token'];
console.log("Token", this.props.myHookValue.state['token']);
let response = fetch('https://x7n8z7pgo5.execute-api.us-east-1.amazonaws.com/dev', {
headers: {
"Authorization": token
}
})
.then(response => response.json())
.then(data => {
console.log("Retrieved Data", data);
this.userData = data["Items"];
console.log("User Data", this.userData);
this.setState([...data["Items"]]); //re-renders data
})
.catch(err => console.log(err));
}
showAddModal = () => {
NiceModal.show(AddModal, { component: this });;
};
render() {
const curData = this.userData;
console.log("Rerendering", curData);
return <div>
<div className="container-xl">
<div className="table-responsive">
<div className="table-wrapper">
<div className="table-title">
<div className="row">
<div className="col-sm-6">
<h2>Manage Clients</h2>
</div>
<div className="col-sm-6">
{<Button className="btn btn-success" type="primary" onClick={this.showAddModal}>
<AddCircle style={this.iconStyles}/> Add New Client
</Button>}
</div>
</div>
</div>
<input id="search" type="text" placeholder="Search..." onKeyUp={search}/>
<Table
size="small"
rowKey="id"
pagination={false}
columns={this.columns}
dataSource={curData}
style={{ marginTop: '20px' }}
/>
</div>
</div>
<div>
</div>
</div>
</div>
}
}
export default withMyHook(UserList);
EditModal.jsx
import { Modal } from 'antd';
import NiceModal, { useModal } from '@ebay/nice-modal-react';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
import { FilePicker, TextInput } from 'evergreen-ui';
import TextArea from 'antd/lib/input/TextArea';
import TextField from '@material-ui/core/TextField';
import { Button } from 'antd';
import React, { useState } from 'react';
function textInputStyles(height='40px') {
return {
width: '350px',
fontSize: '20px',
height: height,
}
}
export default NiceModal.create(({ data, onEdit }) => {
const user = data;
const [firstName, setFirstName] = useState(user.First_Name);
const [lastName, setLastName] = useState(user.Last_Name);
const [address, setAddress] = useState(user.Address);
const [billed, setBilled] = useState(user.Billed);
const [workDate, setWorkDate] = useState(user.Work_Date);
const [notes, setNotes] = useState(user.Notes);
const modal = useModal();
return (
<Dialog
open={modal.visible}
onClose={() => {
modal.hide();
}}
TransitionProps={{
onExited: () => modal.remove(),
}}
>
<DialogTitle id="edit">{"Edit Client"}</DialogTitle><hr></hr>
<DialogContent>
<DialogContentText id="edit_first_name">
First Name
</DialogContentText>
<DialogContentText>
<TextInput
style={textInputStyles()}
defaultValue={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
</DialogContentText>
<DialogContentText id="edit_last_name">
Last Name
</DialogContentText>
<DialogContentText>
<TextInput
style={textInputStyles()}
defaultValue={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
</DialogContentText>
<DialogContentText id="edit_address">
Address
</DialogContentText>
<DialogContentText>
<TextInput
style={textInputStyles()}
defaultValue={address}
onChange={(e) => setAddress(e)}
/>
</DialogContentText>
<DialogContentText id="edit_billed">
Billed
</DialogContentText>
<DialogContentText>
<TextInput
style={textInputStyles()}
defaultValue={billed}
/>
</DialogContentText>
<DialogContentText id="edit_work_date">
Work Date
</DialogContentText>
<DialogContentText>
<TextField
id="date"
label=""
type="date"
InputLabelProps={{
shrink: true,
}}
defaultValue={new Date(workDate).toISOString().substring(0, 10)}
/>
</DialogContentText>
<DialogContentText id="edit_last_modified_date">
Today's Date
</DialogContentText>
<DialogContentText>
<TextInput
style={textInputStyles()}
value={new Date().toDateString().split(' ').slice(1).join(' ')}
editable={false}
/>
</DialogContentText>
<DialogContentText id="edit_notes">
Notes
</DialogContentText>
<DialogContentText>
<TextArea
style={textInputStyles(175)}
editable={false}
defaultValue={notes}
/>
</DialogContentText>
<DialogContentText>
Invoice
</DialogContentText>
<DialogContentText>
<FilePicker>
onClick={}
</FilePicker>
</DialogContentText>
</DialogContent>
<DialogActions style={{backgroundColor:'#D3D3D3', justifyContent: 'space-between'}}>
<Button onClick={() => modal.hide()} className="btn" style={{backgroundColor:'red', width: '25%'}}>
Cancel
</Button>
<Button onClick={() => {
modal.hide();
const updatedUser = {
'Address': 'asd',
'First_Name': 'asd',
'Billed': '123',
'Index': user.Index,
'Last_Name': 'fadsad',
'Notes': 'sdad',
'Table_Date': new Date(workDate).toISOString().substring(0, 10),
'Work_Date': workDate
};
onEdit(updatedUser);
}} className="btn" style={{backgroundColor: '#47b300', color:'white', width: '25%', float:'right'}}>
Add
</Button>
</DialogActions>
</Dialog>
);
});
2
Answers
Antd Table
s require a copy of the data to be able to dynamically update the table.Maybe here in componentDidMount and ShowEditModal (but we don’t the server response format) in UserList component