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));
Related
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>
I have an object containing an array of objects
initialPreconfigTodoState = {
todos: [
{
title: 'title1',
dueDate: new Date(),
create: true,
assignedTo: 'role',
},
{
title: 'title2',
dueDate: new Date(),
create: true,
assignedTo: 'role',
}]
};
I use this array of object to control the state of a Textfield in a table
const [preconfig, setPreconfig] = useState(initialPreconfigTodoState);
{preconfig.todos.map((todo, index) => {
return (
<TableRow
className="h-64 cursor-pointer"
key={Math.random()}
>
<TableCell className="th" component="th" scope="row">
<TextField
id={`titleForm${index}`}
name={`titleForm${index}`}
onChange={(event) => handleTitle(event, index)}
value={todo.title}
type="text"
variant="outlined"
required={todo.create ? true : false}
fullWidth
/>
</TableCell>
when I try to type in the Textfield I don't know what happens but I need to click the Textfield for every character I type, I think is the useState hook that is causing this problem when re-rendering the component and I can't find a solution for this.
this is my handle function on the onChange Callback,
const handleTitle = (event, index) => {
let newArray = [...preconfig.todos];
newArray[index] = {
...newArray[index],
title: event.target.value,
};
setPreconfig({ todos: newArray });
};
here is the full code
const initialPreconfigTodoState = {
todos: [
{
title: "title1",
dueDate: new Date(),
create: true,
assignedTo: "Role"
},
{
title: "title2",
dueDate: new Date(),
create: true,
assignedTo: "Role"
}
]
};
function TodoDialog() {
const [preconfig, setPreconfig] =
useState(initialPreconfigTodoState);
const handleTitle = (event, index) => {
let newArray = [...preconfig.todos];
newArray[index] = {
...newArray[index],
title: event.target.value
};
setPreconfig({ todos: newArray });
};
return (
<div>
<Dialog open={true} maxWidth="xl" scroll="paper">
<DialogContent>
<div>
<Table aria-labelledby="tableTitle">
<TableBody>
<TableRow className="h-64 cursor-pointer" key=.
{Math.random()}>
<TableCell className="th" component="th" scope="row">
Title
</TableCell>
<TableCell className="th" component="th" scope="row">
Due Date
</TableCell>
<TableCell className="th" component="th" scope="row">
Asigned To
</TableCell>
<TableCell className="th" component="th" scope="row">
Create
</TableCell>
</TableRow>
{preconfig.todos.map((todo, index) => {
return (
<TableRow
className="h-64 cursor-pointer"
key={Math.random()}
>
<TableCell className="th" component="th" scope="row">
<TextField
id={`titleForm${index}`}
name={`titleForm${index}`}
onChange={(event) => handleTitle(event, index)}
value={todo.title}
type="text"
variant="outlined"
required={todo.create ? true : false}
fullWidth
/>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
</DialogContent>
<DialogActions>
<Button color="primary" variant="contained">
Cancel
</Button>
<Button type="submit" color="primary" variant="contained" autoFocus>
Save
</Button>
</DialogActions>
</Dialog>
</div>
);
}
That's because the key={Math.random()} on TableRow.
Change it to key={index} and it should work.
With the Math.random() your keys changes every rendering and react loses its reference.
The issue is caused by thenuseState indeed. Your whole form (I suppose it's a form of some kind) changes the array from which it's mapped in render. No wonder the whole form re-renders.
The obvious solution would be to store the input values (eg in state) and update the original array (via setPreconfig) only on submit.
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>
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>
);
}
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>