Topic: MDBDatatable not updating new rows per useState
Bridget Melvin pro premium asked 2 years ago
*Expected behavior*I have a rather complicated set of HOC and a CompaniesTable
component with state data that is properly reflecting when a new Company object is added to the array. I expected the datatable to update for new rows but it does not.
*Actual behavior*The datatable never re-renders for new data.
Resources (screenshots, code snippets etc.)
CompaniesTable.js
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { MDBDatatable, MDBBtn, MDBIcon } from 'mdbReactUiKit';
import styled from 'styled-components';
import { strToUrl } from 'containerMfe/Functions';
const Frame = styled.div`
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> * > .form-outline {
align-self: flex-start;
width: 50%;
}
`
const TableDiv = styled.div`
width: fit-content;
padding: 20px;
`
const StyledButton = styled(MDBBtn)`
padding: 3px!important;
margin: 3px!important;
`
const StyledTable = styled(MDBDatatable)`
align: center;
width: fit-content;
min-width: 800px;
max-width: 1200px;
& td {
margin-bottom: 0!important;
padding-bottom: 6px! important;
}
`
export default function CompaniesTable({ companies, activeUser, onNavigateCompany, onNewCompany }) {
console.log('in CompaniesTable.js', companies, activeUser)
const [actionData, setActionData] = useState({
columns: companies.columns,
rows: addActionButtons(companies.rows)
});
useEffect(() => {
console.log('useEffect CompaniesTable.js', companies)
setActionData({
columns: companies.columns,
rows: addActionButtons(companies.rows)
})
}, [companies])
const setLastCompany = (newCompanyName) => {
const prevCompany = companies.rows.filter(entry => entry.last === true)[0]
let newCompany = prevCompany
if (prevCompany.name !== newCompanyName) {
prevCompany.last = false;
newCompany = companies.rows.filter(entry => entry.condensedName === strToUrl(newCompanyName))[0]
newCompany.last = true;
// console.log('previous company', prevCompany.name, prevCompany.last, newCompanyName, newCompany)
}
onNavigateCompany(prevCompany, newCompany)
}
function addActionButtons(rows) {
return rows.map((row) => {
return {
...row,
action: (
<Link to={`/companies/${strToUrl(row.name)}`} >
<StyledButton outline size='sm' floating className='arrow-btn' onClick={() => setLastCompany(row.name)}>
<MDBIcon icon='arrow-right' />
</StyledButton>
</Link>
),
}
})
}
return (
<StyledContainer>
<TableDiv>
<StyledTable
hover
search
striped
fixedHeader
maxHeight='460px'
data={actionData}
entriesOptions={[5, 10, 20]}
entries={10}
/>
</TableDiv>
</StyledContainer>
)
}
Companies.js
import React, { useState, useEffect } from 'react';
import styled, { createGlobalStyle } from 'styled-components';
import CompaniesHeading from './companies/CompaniesHeading';
import CompaniesTable from './companies/CompaniesTable';
import AddCompany from './modals/AddCompany';
import { ucols, adminPermissions } from '../data-variables/users';
import GetRandomBanner from './companies/GetRandomBanner';
const GlobalStyle = createGlobalStyle`
body {
height: 100%;
min-height: 100vh;
}
html {
height: 100%;
}
`
const Wrapper = styled.div`
left: 0;
background-color: #fff;
min-height: 100vh;
`
const Main = styled.main`
margin: 0;
padding: 10px 50px;
position: relative;
max-height: 100%;
height: 100%;
min-height: 100vh;
width: 100%;
display: flex;
flex-direction: column;
`
const Content = styled.div`
display: block;
top: 0;
left: 0;
color: #000;
font-family: Barlow;
`
export default function Companies({ firm, companies, activeUser, onNavigateCompany, onAddCompany, onUpdateUsers }) {
// BEM TO DO: create state on add/remove company
const [showAddCompanyModal, setShowAddCompanyModal] = useState(false);
const [userCompanies, setUserCompanies] = useState({
columns: companies.columns,
rows: companies.rows.filter(company => activeUser.companies.includes(company.id)).map(company => {
let r = 'User';
if (activeUser.roles.admin.includes(company.id)) {
r = 'Admin';
} else if (activeUser.roles.collaborator.includes(company.id)) {
r = 'Collaborator'
} else if (activeUser.roles.viewer.includes(company.id) && activeUser.emailraw.slice(activeUser.emailraw.search('@')) !== company.firmDomain) {
// console.log(user.emailraw.slice(user.emailraw.search('@')), )
r = 'External User'
}
return { ...company, role: r }
})
})
const openNewCompanyModal = () => {
setShowAddCompanyModal(true);
}
const closeNewComapnyModal = () => {
// BEM TO DO: add comapny to companies list
setShowAddCompanyModal(false);
}
const passNewCompanyHandler = (company) => {
setUserCompanies(prevState => ({
...prevState,
rows: [
...prevState.rows,
company
]
}))
return company
}
const addNewCompanyHandler = (newCompany) => {
const companyId = (firm.companies.rows.length + 1)
const newAdminRoles = [...activeUser.adminRoles, companyId]
console.log('newAdminRoles', newAdminRoles)
const c = {
id: companyId,
firmId: firm.id,
firms: [firm.id],
firmDomain: firm.domain,
name: newCompany.enteredName,
description: newCompany.description,
location: newCompany.location,
sector: newCompany.sector,
website: newCompany.website,
banner: GetRandomBanner(),
admin: activeUser,
adminId: activeUser.id,
connection: false,
collaboratorIds: [],
userIds: [activeUser.id],
last: false,
users: {
columns: ucols,
rows: [{
...activeUser,
adminRoles: newAdminRoles,
roles: {
...activeUser.roles,
admin: activeUser.roles.admin.push(companyId)
},
permissions: {
...activeUser.permissions,
[companyId]: adminPermissions
}
}]
}
}
// BEM TO DO: update activeUser and Users for new role
let u = {
...activeUser,
roles: {
...activeUser.roles,
adminRoles: newAdminRoles,
roles: {
...activeUser.roles,
admin: newAdminRoles,
},
permissions: {
...activeUser.permissions,
[companyId]: adminPermissions
}
}
}
onAddCompany(c, u)
passNewCompanyHandler(c)
}
return (
<React.Fragment>
<GlobalStyle />
<Wrapper>
{showAddCompanyModal ?
<AddCompany
onAddCompany={addNewCompanyHandler}
showModal={showAddCompanyModal}
closeModal={closeNewComapnyModal}
/> :
''}
<Main>
<Content>
<CompaniesHeading companies={userCompanies} openModal={openNewCompanyModal} />
<CompaniesTable
companies={userCompanies}
activeUser={activeUser}
onNewCompany={passNewCompanyHandler}
onNavigateCompany={onNavigateCompany}
/>
</Content>
</Main>
</Wrapper>
</React.Fragment>
);
}
App.js
import React, { useEffect, useState } from 'react';
import { Switch, Route, Router } from 'react-router-dom';
import { port } from './data-variables/global';
import "./assets/css/mdb.css";
import Companies from './components/Companies';
import Company from './components/Company';
import NavbarDev from './components/NavbarDev';
import App from './components/test/08-finished/src/App'
import { firms } from './data-variables/firms'
import WebFont from 'webfontloader';
if (process.env.NODE_ENV === 'development') {
WebFont.load({
google: {
families: ['Barlow', 'Playfair Display', 'Overpass', 'Montserrat']
}
});
}
export default ({ history }) => {
let whatPort = location.port;
const [firmData, setFirmData] = useState(firms[0]) // Rock Equity (BEM TO DO)
const [companiesData, setCompaniesData] = useState(firmData.companies)
const [company, setCompany] = useState(companiesData.rows.filter(entry => entry.last === true)[0])
const [ActiveUser, setActiveUser] = useState(company.users.rows.filter(entry => entry.id === 1)[0]) // Jennifer Doe .. BEM TO DO: set at Auth per user session
console.log('firmData', firmData)
useEffect(() => {
history.push('/companies')
}, [])
console.log('in App.js', companiesData)
function NewDevHome() {
return (
<React.Fragment>
<h1>heyyyy</h1>
</React.Fragment>
)
}
const onNavigateCompany = (oldCompany, newCompany) => {
// update last company on navigate
if (oldCompany.id !== newCompany.id) {
let newCompanies = companiesData.rows.map(c => {
if (c.id !== oldCompany.id && c.id !== newCompany.id) {
return c
} else if (c.id === oldCompany.id) {
return oldCompany
} else {
return newCompany
}
})
// update companiesData to persist the change
setCompaniesData(prevState => ({
...prevState,
rows: newCompanies
}))
}
setCompany(newCompany)
}
// BEM TO DO: causing Cognitive Complexity to be too high
const updateFirmHandler = (enteredCompaniesData, newUsersData) => {
if (newUsersData === []) {
setFirmData(prevState => ({
...prevState,
companies: {
...prevState.companies,
rows: [...enteredCompaniesData]
},
}))
} else if (enteredCompaniesData === []) {
console.log('here')
setFirmData(prevState => ({
...prevState,
users: {
...prevState.users,
rows: [...newUsersData]
}
}))
} else {
setFirmData(prevState => ({
...prevState,
companies: {
...prevState.companies,
rows: [...enteredCompaniesData]
},
users: {
...prevState.users,
rows: [...newUsersData]
}
}))
}
}
const updateCompanyHandler = (updatedCompanyData) => {
if (company.id === updatedCompanyData.id) {
setCompany(updatedCompanyData)
}
let newCompanies = companiesData.rows.map(c => {
if (c.id === updatedCompanyData.id) {
return updatedCompanyData
} else {
return c
}
})
if (!newCompanies.includes(updatedCompanyData.id)) {
newCompanies = [...newCompanies, updatedCompanyData]
}
console.log('updateCompanyHandler App.js', newCompanies)
setCompaniesData(prevState => ({
...prevState,
rows: newCompanies
}))
}
const updateForNewCompany = (newCompany, newUserData) => {
console.log('newCompany App.js', newCompany)
updateCompanyHandler(newCompany)
updateUsersForNewCompany(newUserData)
}
const updateCompanyForUsers = (updatedUsersData) => {
setCompany(prevState => ({
...prevState,
users: {
...prevState.users,
rows: updatedUsersData
}
}))
let newCompanies = companiesData.rows.map(c => {
if (c.id === company.id) {
return {
...company,
users: {
...company.users,
rows: updatedUsersData
}
}
} else {
return c
}
})
setCompaniesData(prevState => ({
...prevState,
rows: newCompanies
}))
console.log('in App.js updateCompanyforUsers', companiesData, updatedUsersData)
}
const updateUsersForNewCompany = (newUserData) => {
let newUsers = firmData.users.rows.map(user => {
if (user.id === newUserData.id) {
return newUserData
} else {
return user
}
})
// console.log('in App.js updateUsersForNewCompany', firmData.users, newUserData, newUsers)
updateUsersHandler(newUsers)
if (ActiveUser.id === newUserData.id) {
setActiveUser(newUserData)
}
}
const updateUsersHandler = (updatedUsersData) => {
// setUsersData(updatedUsersData)
// BEM TO DO: update Companies per Company per user change
// console.log('in App.js updateUsersHandler', updatedUsersData)
updateCompanyForUsers(updatedUsersData)
updateFirmHandler([], updatedUsersData)
}
const addConnectionHandler = (company) => {
let c = { ...company, connection: true }
updateCompanyHandler(c)
}
return (
<Router history={history}>
{(process.env.NODE_ENV === 'development' && whatPort === port.toString()) ? <NavbarDev /> : ''}
<Switch>
<Route exact path="/companies/last">
<Company
companies={companiesData}
onNavigateCompany={onNavigateCompany}
activeUser={ActiveUser}
setActiveUser={setActiveUser}
onUpdateCompanies={(data) => updateCompanyHandler(data)}
onUpdateUsers={(data) => updateUsersHandler(data)}
onAddConnection={addConnectionHandler}
/>
</Route>
<Route path='/companies/:companyName'>
<Company
companies={companiesData}
onNavigateCompany={onNavigateCompany}
activeUser={ActiveUser}
setActiveUser={setActiveUser}
onUpdateCompanies={(data) => updateCompanyHandler(data)}
onUpdateUsers={(data) => updateUsersHandler(data)}
onAddConnection={addConnectionHandler}
/>
</Route>
<Route exact path="/user/settings">
{/* <Companies companies={firmData.companies} /> */}
<App />
</Route>
<Route exact path="/companies">
<Companies
firm={firmData}
companies={companiesData}
onNavigateCompany={onNavigateCompany}
activeUser={ActiveUser}
onAddCompany={updateForNewCompany}
/>
</Route>
<Route path='/' component={NewDevHome} />
</Switch>
</Router>
);
};
Wojciech Staniszewski staff answered 2 years ago
You probably are not using useEffect
hook correctly. Please check again, if the actionData
changes properly.
Bridget Melvin pro premium commented 2 years ago
what am I doing wrong?
Bridget Melvin pro premium commented 2 years ago
I tried updating it to ....
useEffect(() => {
console.log('useEffect CompaniesTable.js', companies)
setActionData(prevState => ({
...prevState,
rows: addActionButtons(companies.rows)
}))
}, [companies])
but it still does not work
Bridget Melvin pro premium commented 2 years ago
I got it to work - nothing with useEffect
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- User: Pro
- Premium support: Yes
- Technology: MDB React
- MDB Version: MDB5 4.1.0
- Device: Surface Laptop Studio
- Browser: Chrome
- OS: Windows 11
- Provided sample code: No
- Provided link: No