This is a bit of a long response, but I am hopeful others might make sense of this for them to implement a similar solution.
So after following the code shown in here, this is what I did that is working:
This is in my Strike.js
file
const GET_STRIKES = gql`
{
Strike {
name
}
}
`;
export default function Strike() {
const classes = useStyles();
const [order, setOrder] = useState("asc");
const [orderBy, setOrderBy] = useState("name");
const handleSortRequest = property => {
const newOrderBy = property;
let newOrder = "desc";
if (orderBy === property && order === "desc") {
newOrder = "asc";
}
setOrder(newOrder);
setOrderBy(newOrderBy);
};
const getSorting = (order, orderBy) => {
return order === "desc"
? (a, b) => (b[orderBy] < a[orderBy] ? -1 : 1)
: (a, b) => (a[orderBy] < b[orderBy] ? -1 : 1);
};
const { loading, error, data } = useQuery(GET_STRIKES);
if (loading) return "Loading...";
if (error) return `Error ${error.message}`;
return (
<div className={classes.root}>
<Grid container spacing={3}>
<Grid item /*xs={12}*/ sm={6}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell
key="name"
sortDirection={orderBy === "name" ? order : false}
>
<Tooltip title="Sort" placement="bottom-start" enterDelay={300}>
<TableSortLabel
active={orderBy === "name"}
direction={order}
onClick={() => handleSortRequest("name")}
>
Name
</TableSortLabel>
</Tooltip>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.Strike //.slice()
.sort(getSorting(order, orderBy))
.map(n => {
return (
<TableRow key={n.name}>
<TableCell component="th" scope="row">
{n.name}
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Grid>
<Grid item /*xs={12}*/ sm={6}>
<RankSelectFilter />
<CreateStrike data={data} GET_STRIKES={GET_STRIKES} />
</Grid>
</Grid>
</div>
);
}
This is in my CreateStrike.js
file:
const CREATE_STRIKE = gql`
mutation CreateStrike($name: String!) {
CreateStrike(name: $name) {
name
}
}
`;
export default function CreateStrike({ data, GET_STRIKES }) {
const classes = useStyles();
const [name, setName] = useState("");
const [CreateStrike] = useMutation(
CREATE_STRIKE,
{
update(cache, { data: { CreateStrike } }) {
const { Strike } = cache.readQuery({ query: GET_STRIKES });
cache.writeQuery({
query: GET_STRIKES,
data: { Strike: Strike.concat([CreateStrike]) },
})
}
}
);
const handleClick = event => {
CreateStrike({
variables: { name: name }
});
}
return (
<div className={classes.root} /*justifyContent="flex-start"*/>
<form className={classes.container} noValidate autoComplete="off">
<CreateStrikeTextField
name={name}
setName={setName}
/>
</form>
<Button
onClick={handleClick}
className={classes.button}
color="primary"
variant="contained"
>
Submit
</Button>
</div>
);
}
The key aspect in Strike.js
was passing data
and GET_STRIKES
to the CreateStrike
component.
<CreateStrike data={data} GET_STRIKES={GET_STRIKES} />
Then in CreateStrike.js
I use the following to run the mutation
and update data
which then causes Strike
to rerender.
const [CreateStrike] = useMutation(
CREATE_STRIKE,
{
update(cache, { data: { CreateStrike } }) {
const { Strike } = cache.readQuery({ query: GET_STRIKES });
cache.writeQuery({
query: GET_STRIKES,
data: { Strike: Strike.concat([CreateStrike]) },
})
}
}
)
I am not entirely certain it is best practice to pass data
like this, but in this instance it works well and I am not needing to use useEffect
.
In summary, the code shown above rerenders a table upon submitting and adding an entry using useQuery
and useMutation
and that does not require useEffect
.