Table generation reactjs - 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>
);
}

Related

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>

useEffect infinite loop WITH empty dependency array

I am dispatching a thunk from my useEffect to populate a table when the page loads. The useEffect keeps running infintely, even though I am using an empty dependency array. Here is my code:
const Cart = (props) => {
const [didFetch, setDidFetch] = useState(false);
useEffect( () => {
async function fetchCart(){
await props.getCartItems();
setDidFetch(true);
}
fetchCart()
return setDidFetch(false)
},[]);
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Product</TableCell>
<TableCell align="right">Quantity</TableCell>
<TableCell align="right">Total Cost</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.cartItems.map((item) => (
<TableRow
key={item.product.name}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row">
{item.product.name}
</TableCell>
<TableCell align="right">{item.quantity}</TableCell>
<TableCell align="right">
{(item.quantity * item.product.price).toFixed(2)}
</TableCell>
<TableCell>
<Button onClick={() => props.removeCartItem(item.id)}>
Remove
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
The cleanup function of useEffect should be an anonymous function, and you shouldn't set state variables inside it, as #windmaomao pointed out, it is a memory leak:
Suggestion
If you want to store a didFetch flag, I would use a ref for this purpose:
import {useRef} from 'react'
const Cart = (props) => {
const fetched = useRef()
useEffect( () => {
async function fetchCart(){
const res = await props.getCartItems();
if(res) fetched.current = true
}
fetchCart()
return () => fetched.current = false
},[]);
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Product</TableCell>
<TableCell align="right">Quantity</TableCell>
<TableCell align="right">Total Cost</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.cartItems.map((item) => (
<TableRow
key={item.product.name}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row">
{item.product.name}
</TableCell>
<TableCell align="right">{item.quantity}</TableCell>
<TableCell align="right">
{(item.quantity * item.product.price).toFixed(2)}
</TableCell>
<TableCell>
<Button onClick={() => props.removeCartItem(item.id)}>
Remove
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
Using your existing code it would be either:
Anonymous function
const [didFetch, setDidFetch] = useState(false);
useEffect( () => {
async function fetchCart(){
await props.getCartItems();
setDidFetch(true);
}
fetchCart()
return () => {
setDidFetch(false);
};
},[]);
Named Function
const [didFetch, setDidFetch] = useState(false);
useEffect( () => {
async function fetchCart(){
await props.getCartItems();
setDidFetch(true);
}
fetchCart()
return function cleanup() {
setDidFetch(false);
};
},[]);
Here are the useEffect docs for reference: https://reactjs.org/docs/hooks-effect.html

ComponentDidMount not firing in ReactJS

I have suddenly run into this problem in my app, the componentDidMount does not work when loading the page and I get typescript error due to the information not being loaded. It was working fine yesterday and the day before and now I have no idea what I did wrong. I have 4 api calls for the method GET, it's only for the GET method. Is there a way to make the component work again ? I have no idea why it behaves this way.
class adminView extends Component {
constructor(props) {
super(props);
this.state = {
Users: [],
Movies: [],
Comments: [],
Ratings: [],
message: null,
};
}
componentDidMount() {
this.reloadObjectiveList().then((r) => console.log("result" + r));
this.reloadUserList().then((r) => {
console.log("result" + r);
});
}
async reloadUserList() {
await UserApiService.fetchUsers().then((res) => {
console.log(res);
this.setState({
Users: res.data.result,
});
});
}
async reloadObjectiveList() {
await UserApiService.fetchUsers().then((res) => {
console.log(res);
this.setState({
Users: res.data.result,
});
});
await MovieApiService.fetchMovies().then((res) => {
this.setState({
Movies: res.data.result,
});
});
await CommentApiService.fetchComments().then((res) => {
console.log(res.data.result);
this.setState({
Comments: res.data.result,
});
});
await RatingApiService.fetchrating().then((res) => {
console.log(res.data.result);
this.setState({
Ratings: res.data.result,
});
});
}
deleteUsersComments(ObjectiveId) {
CommentApiService.deleteComment(ObjectiveId).then((res) => {
this.setState({ message: "Objective deleted successfully." });
this.setState({
Comments: this.state.Comments.filter(
(Objective) => Objective.username !== ObjectiveId
),
});
});
}
deleteUsersRatingss(ObjectiveId) {
RatingApiService.deleterating(ObjectiveId).then((res) => {
this.setState({ message: "Objective deleted successfully." });
this.setState({
Ratings: this.state.Ratings.filter(
(Objective) => Objective.username !== ObjectiveId
),
});
});
}
deleteMovies(ObjectiveId) {
MovieApiService.deleteTourist(ObjectiveId).then((res) => {
this.setState({ message: "Objective deleted successfully." });
this.setState({
Movies: this.state.Movies.filter(
(Objective) => Objective.imdb_id !== ObjectiveId
),
});
});
}
deleteUsers(ObjectiveId) {
UserApiService.deleteTourist(ObjectiveId).then((res) => {
this.setState({ message: "Objective deleted successfully." });
this.setState({
Movies: this.state.Movies.filter(
(Objective) => Objective.username !== ObjectiveId
),
});
});
}
render() {
const { details, loading } = this.props;
return (
<main className={styles.main}>
<Paper className={styles.paper}>
<Typography component="h1" variant="h5">
Hello ADMIN
</Typography>
<hr />
<Typography component="h1" variant="h5">
Users:
</Typography>
<div className="card-list">
{console.log(this.state.Users)}
{this.state.Users.map((item) => (
<CardUsers item={item} key={item.username} />
))}
</div>
<Table>
<TableHead>
<TableRow>
<TableCell>UserFirstName</TableCell>
<TableCell>UserLastName</TableCell>
<TableCell>UserEmail</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.state.Users.map((row) => (
<TableRow key={row.username}>
<TableCell align="center">{row.firstName}</TableCell>
<TableCell align="center">{row.lastName}</TableCell>
<TableCell align="center">{row.email}</TableCell>
<TableCell
align="center"
onClick={() => this.deleteUsers(row.username)}
>
<DeleteIcon />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
<hr />
<Typography component="h1" variant="h5">
MOVIES
</Typography>
<hr />
<div className="card-list">
<Card item={this.state.Movies} />
</div>
<Typography component="h1" variant="h5">
Comments
</Typography>
<hr />
<hr />
<Table>
<TableHead>
<TableRow>
<TableCell>UserId</TableCell>
<TableCell>Comment</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.state.Comments.map((row) => (
<TableRow key={row.username}>
<TableCell align="center">{row.username}</TableCell>
<TableHead>
<TableCell>MovieID</TableCell>
<TableCell>Comment</TableCell>
</TableHead>
<TableBody>
{row.commentsList.map((row2) => (
<TableRow key={row2.id}>
<TableCell align="center">{row2.movieID}</TableCell>
<TableCell align="center">{row2.comment}</TableCell>
<TableCell
align="center"
onClick={() => this.deleteUsersComments(row2)}
>
<DeleteIcon />
</TableCell>
</TableRow>
))}
</TableBody>
</TableRow>
))}
</TableBody>
</Table>
<Typography component="h1" variant="h5">
Ratings
</Typography>
<hr />
<hr />
<Table>
<TableHead>
<TableRow>
<TableCell>UserId</TableCell>
<TableCell>Ratings</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.state.Ratings.map((row) => (
<TableRow key={row.username}>
<TableCell align="center">{row.username}</TableCell>
<TableHead>
<TableCell>MovieID</TableCell>
<TableCell>Rating</TableCell>
</TableHead>
<TableBody>
{row.ratingsList.map((row2) => (
<TableRow key={row2.id}>
<TableCell align="center">{row2.movieID}</TableCell>
<TableCell align="center">{row2.rating}</TableCell>
<TableCell
align="center"
onClick={() => this.deleteUsersRatingss(row2)}
>
<DeleteIcon />
</TableCell>
</TableRow>
))}
</TableBody>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
</main>
);
}
}
export default withRouter(withStyles(styles)(adminView));

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>

react-sortable-hoc stops after first move with edgeOffset

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>

Resources