react-sortable-hoc stops after first move with edgeOffset - reactjs

I'm attempting to make a sortable table with react-sortable-hoc. This works fine for the first move but afterwards, react-sortable-hoc will stop working. The row in the table no longer animates and attempting to move an item throws the following error:
TypeError: edgeOffset is undefined
This is the relevant code:
const DragHandle = SortableHandle(() => <DragIndicatorIcon />);
const SortableItem = SortableElement(({ value, sortIndex, groupType }) => {
return (
<TableRow
hover
key={value.id}
index={sortIndex}
>
<TableCell><DragHandle /></TableCell>
<TableCell component="th" scope="row">
{value.fullname}
</TableCell>
<TableCell numeric>{value.number}</TableCell>
{groupType &&
<TableCell>10</TableCell>
}
</TableRow>
);
});
const SortableList = SortableContainer(({ items, groupType }) => {
return (
<TableBody>
{items.map((user, index) => {
return (
<SortableItem key={`item-${index}`} groupType={groupType} index={index} sortIndex={index} value={user} />
);
})}
</TableBody>
);
});
And:
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell />
<TableCell>Name</TableCell>
<TableCell numeric>Number</TableCell>
{this.props.groupType === "1" &&
<TableCell>Seconds</TableCell>
}
</TableRow>
</TableHead>
<SortableList items={this.props.items} groupType={this.props.groupType === "1"} onSortEnd={this.props.onSortEnd} useDragHandle={true} useWindowAsScrollContainer={true} />
</Table>

Related

reactjs conditional statement inside TableCell

How do I input conditional if else statement in a TableCell for ReactJS. I want the data table to output nothing is found if the search box returns nothing.
Here is the code:
export default function DataTable () {
const [query, setQuery] = useState('')
const [tableData, setTableData] = useState([])
useEffect( function () {
const fetchUsers = async function () {
const response = await axios.get(`/search/?query=${query}`)
setTableData(response.data)
}
if (query.length === 0 || query.length > 2) fetchUsers()
}, [query])
return (
<>
<input type={'text'} placeholder={'Enter Teacher ID Number....'} className='search-bar' onChange={(event) => setQuery(event.target.value)} />
<TableContainer component={Paper} className='data-table'>
<Table sx={{minWidth: 650}} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell className='tableCell'>ID</TableCell>
<TableCell className='tableCell'>Name</TableCell>
<TableCell className='tableCell'>Surname</TableCell>
<TableCell className='tableCell'>Title</TableCell>
<TableCell className='tableCell'>Email</TableCell>
<TableCell className='tableCell'>Action #1</TableCell>
<TableCell className='tableCell'>Action #2</TableCell>
</TableRow>
</TableHead>
<TableBody>
{ tableData.map((data) => (
<TableRow key={data.id} sx={{ '&:last-child td, &:last-child th': {border:0}}}>
<TableCell className='tableCell'> { data.id }</TableCell>
<TableCell className='tableCell'> { data.name }</TableCell>
<TableCell className='tableCell'> { data.surname }</TableCell>
<TableCell className='tableCell'> { data.title }</TableCell>
<TableCell className='tableCell'> { data.email}</TableCell>
<TableCell className='tableCell'>
<button className={'verify'}>
<Link to={`/search/${data.id}`} className={'verify'} state={data}>Verify</Link>
</button>
</TableCell>
<TableCell className='tableCell'>
<button className={`drop`}>
<Link to={`/drop/${data.id}`} className={'drop'} state={data}>Drop</Link>
</button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
)
}
I tried to input ternary operator '?' but it returns the first result
First of all I recommend to you separate the mapped Row in a separated component to handle easily and get the code more readable. This component could be in other file.
On the other hand I highly recommend if you are consuming the data from rest service, is using React Query.
export default function DataTable () {
const [query, setQuery] = useState('')
const [tableData, setTableData] = useState([])
useEffect( function () {
const fetchUsers = async function () {
const response = await axios.get(`/search/?query=${query}`)
setTableData(response.data)
}
if (query.length === 0 || query.length > 2) fetchUsers()
}, [query])
function UserTableRow(user){
return (
<TableRow key={user.id} sx={{ '&:last-child td, &:last-child th': {border:0}}}>
<TableCell className='tableCell'> { user.id }</TableCell>
<TableCell className='tableCell'> { user.name }</TableCell>
<TableCell className='tableCell'> { user.surname }</TableCell>
<TableCell className='tableCell'> { user.title }</TableCell>
<TableCell className='tableCell'> { user.email}</TableCell>
<TableCell className='tableCell'>
<button className={'verify'}>
<Link to={`/search/${user.id}`} className={'verify'} state={data}>Verify</Link>
</button>
</TableCell>
<TableCell className='tableCell'>
<button className={`drop`}>
<Link to={`/drop/${user.id}`} className={'drop'} state={data}>Drop</Link>
</button>
</TableCell>
</TableRow>
)
}
return (
<>
<input type={'text'} placeholder={'Enter Teacher ID Number....'} className='search-bar' onChange={(event) => setQuery(event.target.value)} />
<TableContainer component={Paper} className='data-table'>
<Table sx={{minWidth: 650}} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell className='tableCell'>ID</TableCell>
<TableCell className='tableCell'>Name</TableCell>
<TableCell className='tableCell'>Surname</TableCell>
<TableCell className='tableCell'>Title</TableCell>
<TableCell className='tableCell'>Email</TableCell>
<TableCell className='tableCell'>Action #1</TableCell>
<TableCell className='tableCell'>Action #2</TableCell>
</TableRow>
</TableHead>
<TableBody>
{ tableData?.map((user) => <UserTableRow user={user}/>)}
{!tableData.length && <div>No results found.</div>}
</TableBody>
</Table>
</TableContainer>
</>
)
}

Where am I missing a key prop here? I'm generating uuids for TableCell keys and I'm using row.id for the row keys

I have this bit of code where I'm getting the warning:
Each child in a list should have a unique "key" prop. Check the render
method of AllPersonnel... at TableRow
And the table cells are not rendering. Any help would be appreciated. Thanks!
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow key={uuidv4()}>
{cols.map((col) => {
return <TableCell key={col.path}>{col.name}</TableCell>
})}
</TableRow>
</TableHead>
<TableBody>
{personnel.map((row, i) => {
return (
<TableRow key={row.id}>
<TableCell key={uuidv4()}>{row.first_name}</TableCell>
<TableCell key={uuidv4()}>{row.last_name}</TableCell>
<TableCell key={uuidv4()}>{row.section}</TableCell>
<TableCell key={uuidv4()}>{row.role}</TableCell>
<TableCell key={uuidv4()}>{row.employee_type}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
You don't need a key on your TableRow, only on the first child in the return of an iterator.
Try :
{personnel.map((row, i) => {
const key = uuidv4()
return (
<TableRow key={key}>
<TableCell>{row.first_name}</TableCell>
...
Normaly...

React - How to break a line in a cell of a material ui table

I'm using the DenseTable component of the ui material and wanted to break a string into parts
here is my table:
I want in the cursos column, in the line that has LEIT - 1st Ano/LEE - 1st Ano I want to break the string where there is the '/'
below my DenseTable component code:
function createData(aulaID, numAula, tipoAula, nome, curso, data, acao) {
return { aulaID, numAula, tipoAula, nome, curso, data, acao };
}
export default function DenseTable() {
const { selectedRow, setSelectedRow, cursoSigla } = useListarAulas();
const [rows, setRows] = React.useState([]);
const {
showLancarSumarioModal,
handleOpenLancarSumarioModal,
handleCloseLancarSumarioModal,
} = useEscreverSumario();
const {
aulas,
// docente,
} = useFiltrarAulas();
React.useEffect(() => {
if (rows.length !== aulas.length) {
const tempRows = [];
aulas.map((aula) =>
tempRows.push(
createData(
aula.id,
aula.numero,
aula.tipo,
aula.disciplina.codigo,
cursoSigla(aula.cursos),
aula.data,
'Lançar Sumario'
)
)
);
setRows(tempRows);
}
}, [aulas, rows]);
return (
<>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell>Disciplina</TableCell>
<TableCell align="right">Curso</TableCell>
<TableCell align="right">Data</TableCell>
<TableCell align="right">Acção</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow
key={row.nome}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell component="th" scope="row">
{row.nome}
</TableCell>
<TableCell align="right">{row.curso}</TableCell>
<TableCell align="right">
{row.data}
{/* moment(row.data).format('yyyy-MM-DD') */}
</TableCell>
<TableCell align="right">
<Button
size="small"
onClick={() => {
setSelectedRow(row);
handleOpenLancarSumarioModal();
}}
>
{row.acao}
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<EscreverSumarioModal
showModal={showLancarSumarioModal}
handleCloseModal={handleCloseLancarSumarioModal}
selectedRow={selectedRow}
/>
</>
);
}
the function cursoSigla() in useEffect receives a courses object where their respective acronyms are and returns a string concatenated with the acronym of each course like this "LEIT - 1º Ano/LEE - 2º Ano"
below the function code:
function cursoSigla(cursos) {
const sigla = [];
if (cursos.length > 1) {
if (sigla.length !== cursos.length) {
cursos.map((curso) => sigla.push(`${curso.sigla} - ${curso.ano}º Ano`));
return sigla.join('/');
}
}
if (cursos.length === 1) {
sigla.push(cursos[0].sigla);
return `${sigla[0]} - ${cursos[0].ano}º Ano`;
}
console.log(sigla);
return '';
}
My question is how to introduce a line break in my table cell ?
Instead of rendering them as:
<TableCell align="right">{row.curso}</TableCell>
You could do something like this instead:
<TableCell>
{row.curso.split("/").map((curs, idx) => (
<p key={idx}>{curs}</p>
))}
</TableCell>

Can't use wrapped fetch component in my .jsx

I have a MainComponentWrapper that is a fetch Get:
export default function MainComponentWrapper({ url, children }) {
const classes = useStyles()
const [data, setData] = React.useState()
React.useEffect(() => {
fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + window.localStorage.getItem("access_token"),
},
})
.then(resp => {
return resp.json()
})
.then(fetchedData => {
setData(fetchedData)
})
.catch(error => {
console.log(error)
window.localStorage.removeItem("access_token")
window.location.replace("/")
})
}, [url])
if (data === undefined) {
return (
<div className={classes.root}>
<CircularProgress className={classes.progress} />
</div>
)
}
return (
<div className={classes.root}>
{React.cloneElement(children, { data: data })}
</div>
)
}
I was trying to use it in my .jsx component so i could get data that i need by passing an api url, and print it on a table.
export default function Machines({data}) {
return (
<div className={classes.root}>
<h1>Azure machines</h1>
<Table className={classes.table} size="small">
<TableHead>
<TableRow>
<TableCell align="left">name</TableCell>
<TableCell align="left">resource_group</TableCell>
<TableCell align="left">location</TableCell>
<TableCell align="left">status</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(row => (
<TableRow key={row.name + row.resource_group}>
<TableCell align="left" component="th" scope="row">
<StyledButton size = "small" className={style.size3}>
<Link style={{ color: 'inherit', textDecoration: 'inherit'}} to={`/machines/${row.resource_group + "/" + row.name}`}>{row.name}</Link>
</StyledButton>
</TableCell>
<TableCell align="left">{row.resource_group}</TableCell>
<TableCell align="left">{row.location}</TableCell>
<MainComponentWrapper url={"/api/machine/one"} >
{({ tmpData }) => (
<TableCell key= {row.location + row.name} log={console.log(data.status)} align="left">
<LoadingIndicator/>
<MachineStatusIcon
status_code={tmpData.status_code}
status={tmpData.status}
/>
</TableCell>
)}
</MainComponentWrapper>
</TableRow>
))}
</TableBody>
</Table>
</div>
)
}
The problem is I can't find a way to use it, I've checked some similar examples but no success.
If i inspect on google chrome and check the network tab i can see that the component is fetching the data, because the data is listed there, but how do i use it to pass as values to my table?
Your MainComponentWrapper is inside where you have 'data' defined. Your wrapper should envelope the entire JSX code which in this case is the table.
<MainComponentWrapper url={"/api/machine/one"} >
<TableBody>
<!-- data is being used here but it didn't exist -->
{data.map(row => (
<TableRow key={row.name + row.resource_group}>
<TableCell align="left" component="th" scope="row">
<StyledButton size = "small" className={style.size3}>
<Link style={{ color: 'inherit', textDecoration: 'inherit'}} to={`/machines/${row.resource_group + "/" + row.name}`}>{row.name}</Link>
</StyledButton>
</TableCell>
<TableCell align="left">{row.resource_group}</TableCell>
<TableCell align="left">{row.location}</TableCell>
{({ tmpData }) => (
<TableCell key= {row.location + row.name} log={console.log(data.status)} align="left">
<LoadingIndicator/>
<MachineStatusIcon
status_code={tmpData.status_code}
status={tmpData.status}
/>
</TableCell>
)}
</TableRow>
))}
</TableBody>
</MainComponentWrapper>

Table generation reactjs

I have algorithm for automatic table generation from arrays.
Array that is called array, after parsing it has look that you can see lower.
const array = [{dfdfd, gdgd, fgdg, dfgdg},
{hjbhjkb, hjybjhy, jhgbjkhy},
{fjkvdnkf, uiholuh, hjyluyg}]
The problem is that with my implementation the subarrays are the rows, whereas I need them to be columns.
class TableGenerator extends React.Component {
render() {
const data = this.props.data
const words = this.props.words
const array = []
console.log(words)
Object.keys(words).forEach(wordIndex => {
const insideObj = words[wordIndex];
const synObj = insideObj.synonyms;
const tempArray = [];
Object.keys(synObj).forEach(objKey => {
tempArray.push(synObj[objKey]);
});
array.push(tempArray);
console.log(array)
})
return (
<Paper style={{ maxWidth: 936, marginLeft: "250px" }}>
<Table>
<TableHead>
<TableRow>
{data.map((TableRow, i) => (
<TableCell key={i} align="center">
{TableRow.split("_").join(" ")}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{array.map((user, i) => (
<TableRow key={i}>
{Object.values(user).map((v, j) => (
<TableCell key={j} align="center">
<IconButton>
<AddIcon/>
</IconButton>
{v}
<IconButton>
<RemoveIcon/>
</IconButton>
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</Paper>
);
}

Resources