Step 19: Navigation
Let’s update the code so when navigate to Edit view we click on edit icon or “add note” button. (We will reuse the same page for adding/editing notes.) Moreover, we should return to the homepage when we click on the “cancel” or “save” buttons in the “edit” page.
pages/Edit.jsx
import { Button, Container, Group, Stack } from "@mantine/core";
import { TextInput, Textarea } from "@mantine/core";
import { useState } from "react";
+ import { useNavigate } from "react-router-dom";
function Edit() {
const [title, setTitle] = useState("");
const [text, setText] = useState("");
+ const navigate = useNavigate();
const handleTitleChange = (event) => {
setTitle(event.target.value);
};
const handleTextChange = (event) => {
setText(event.target.value);
};
const handleSave = () => {
console.log({ title, text });
+ navigate("/", { replace: true });
};
const handleCancel = () => {
console.log("cancel");
+ navigate("/", { replace: true });
};
return (
<Container>
<Stack spacing="lg">
<TextInput
placeholder="Your note's title"
label="Title"
withAsterisk
value={title}
onChange={handleTitleChange}
/>
<Textarea
placeholder="Your note's text"
label="Text"
withAsterisk
autosize
minRows={5}
value={text}
onChange={handleTextChange}
/>
<Group position="center" spacing="xl" grow>
<Button variant="subtle" onClick={handleCancel}>
Cancel
</Button>
<Button variant="default" onClick={handleSave}>
Save
</Button>
</Group>
</Stack>
</Container>
);
}
export default Edit;
components/Header.jsx
import { IconNote } from "@tabler/icons";
import { Grid, Button } from "@mantine/core";
import Search from "./Search";
import PropTypes from "prop-types";
+ import { useNavigate } from "react-router-dom";
function Header(props) {
const { query, setQuery, add } = props;
+ const navigate = useNavigate();
const handleOnClick = () => {
add();
+ navigate("/edit");
};
return (
<Grid>
<Grid.Col span={10}>
<Search query={query} setQuery={setQuery} />
</Grid.Col>
<Grid.Col span={2}>
<Button
onClick={handleOnClick}
fullWidth
variant="default"
leftIcon={<IconNote />}
>
Add Note
</Button>
</Grid.Col>
</Grid>
);
}
export default Header;
Header.propTypes = {
query: PropTypes.string,
setQuery: PropTypes.func,
add: PropTypes.func,
};
components/NoteControl.jsx
import PropTypes from "prop-types";
import { Accordion, ActionIcon, Box } from "@mantine/core";
import { IconTrashX, IconPencil } from "@tabler/icons";
+ import { useNavigate } from "react-router-dom";
function NoteControl(props) {
const { note, remove } = props;
const { id, title } = note;
+ const navigate = useNavigate();
const handleOnEdit = () => {
+ navigate("/edit");
};
const handleOnRemove = () => {
remove(id);
};
return (
<Box sx={{ display: "flex", alignItems: "center" }}>
<Accordion.Control>{title}</Accordion.Control>
<ActionIcon onClick={handleOnEdit} size="lg">
<IconPencil size={16} />
</ActionIcon>
<ActionIcon onClick={handleOnRemove} size="lg">
<IconTrashX size={16} />
</ActionIcon>
</Box>
);
}
export default NoteControl;
NoteControl.propTypes = {
remove: PropTypes.func.isRequired,
note: PropTypes.shape({
title: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
}),
};
Notice in all the these cases, we used the useNavigate
hook for navigation.
The
useNavigate
hook returns a function that lets you navigate programmatically.
Observe the app’s behaviour in the browser!