preface
Today is the third day of learning React. My first small goal is to implement all functions of the todo manifest software on the Web side by one-for-one!
It is recommended to pull the project code together with the edible effect of the React-Todo Gitee repository
Everything written before will be in the preface:
Create react App+Tailwind CSS +Material UI
# 👀 configure Eslint+ router-dom route navigation for React
Development tasks
Today’s tasks are:
Separate the left menu bar from yesterday’s development into separate components, as shown below
Realize a top bar date function in the Day Todo function module, as shown in the figure below
The development of
Eslint-plugin-react-hooks I added a new esLint plugin according to the official documentation before today’s development
Let’s install it by executing the command
yarn add eslint-plugin-react-hooks --save-dev
Copy the code
Then declare the plugin in.eslintrc.js. The complete configuration is as follows
module.exports = {
root: true.env: {
browser: true.es2021: true,},extends: ["eslint:recommended"."plugin:react/recommended"].parserOptions: {
ecmaFeatures: {
jsx: true,},ecmaVersion: 2018.sourceType: "module",},plugins: ["react"."react-hooks"].rules: {
semi: [2."never"]."react-hooks/rules-of-hooks": "error".// Check the Hook rules
"react-hooks/exhaustive-deps": "warn".// Check for effect dependencies}},Copy the code
Eslint-plugin-react-hooks specify the following rules:
Only the React function calls the Hook
Never call a Hook in a normal JavaScript function. You can:
- ✅ calls the Hook in the React function component
- ✅ calls other hooks in custom hooks
Extract the LeftNav component
We create a new LeftNav component in the Layout directory and extract the relevant code from the left column.
// /layout/LeftNav.jsx
import React from "react"
import PropTypes from "prop-types"
import { Link } from "react-router-dom"
import { List, ListItem, ListItemButton, ListItemIcon } from "@mui/material"
import WbSunnyOutlinedIcon from "@mui/icons-material/WbSunnyOutlined"
import CalendarTodayOutlinedIcon from "@mui/icons-material/CalendarTodayOutlined"
import CalendarViewMonthOutlinedIcon from "@mui/icons-material/CalendarViewMonthOutlined"
import InboxOutlinedIcon from "@mui/icons-material/InboxOutlined"
import SearchOutlinedIcon from "@mui/icons-material/SearchOutlined"
import ListAltOutlinedIcon from "@mui/icons-material/ListAltOutlined"
LeftNav.propTypes = {
active: PropTypes.string,
changeActive: PropTypes.func,
}
export default function LeftNav(props) {
const { active, changeActive } = props
const data = [
{ icon: <WbSunnyOutlinedIcon />, label: "Day Todo".path: "dayTodo" },
{
icon: <CalendarTodayOutlinedIcon />,
label: "To do.".path: "recentlyTodo"}, {icon: <CalendarViewMonthOutlinedIcon />,
label: "Date Overview".path: "dateOverview"}, {icon: <InboxOutlinedIcon />, label: "To-do box".path: "todyBox" },
{ icon: <SearchOutlinedIcon />, label: "Search".path: "search" },
{ icon: <ListAltOutlinedIcon />, label: "Data recovery".path: "dataReview"},]return (
<List>
{data.map((item) => {
return (
<Link to={item.path} key={item.path}>
<ListItem
disablePadding
className={item.path= = =active ? "bg-gray-200" : ""}
onClick={()= > changeActive(item.path)}
>
<ListItemButton>
<ListItemIcon>{item.icon}</ListItemIcon>
<span className="text-sm">{item.label}</span>
</ListItemButton>
</ListItem>
</Link>)})}</List>)}Copy the code
The original page was much cleaner. I changed the active and setAcitve variables defined by hook to be defined in the page and passed LeftNav as component parameters.
Since esLint also declares the prop type of the component, the PropTypes type validator is used according to the official documentation.
Here is the code for the page after the component is removed:
// layout/index.jsx
import React, { useState } from "react"
import routes from ".. /routes"
import { Route, Routes } from "react-router-dom"
import { Button, Card } from "@mui/material"
import LeftNav from "./LeftNav"
export default function Layout() {
const [active, setActive] = useState("dayTodo")
return (
<div className="w-screen h-screen flex items-center justify-center">
<Card variant="outlined" className="w-2/3 h-3/4 shadow-lg bg-white flex">
<div className="w-1/5 bg-gray-50">
<div className=" flex items-center justify-center p-5">
<Button variant="contained">This is a button</Button>
</div>
<LeftNav
active={active}
changeActive={(active)= > setActive(active)}
/>
</div>
<div className=" w-4/5">
<Routes>
{routes.map((item) => {
return (
<Route
index={item.path= = =active}
key={item.path}
exact
path={item.path}
element={item.component()}
></Route>)})}</Routes>
</div>
</Card>
</div>)}Copy the code
Implement the top bar date
Let’s first analyze the requirements:
- The default is to display seven dates for the week, and today’s date will light up
- On the right is the specific time, and if we select another date, the activation lit up date and the specific time on the right will also change. If you click on the right side of the specific time will pop up a complete calendar
- Click on the sun icon to return to today’s date
- Click left and right respectively to switch to the date of last week or next week
Start by creating a new DatePicker component in the DayTodo directory to write our top date selection bar as a separate component and reference it in the page.
The introduction of Day. Js
According to the above requirement analysis, the data we need to obtain are today’s date and seven dates of each week. I will choose day. js js library for such operations frequently involving time processing.
Day.js is a minimalist JavaScript library that parses, validates, manipulates, and displays dates and times for modern browsers. Day.js official documentation link
First let’s install the library
yarn add dayjs
Copy the code
We then introduce the DatePicker component as follows:
// dayTodo/DatePick.jsx
import React from 'react';
import dayjs from 'dayjs';
import isoWeek from 'dayjs/plugin/isoWeek'
dayjs.extend(isoWeek)
export default function DatePicker(){
const today = dayjs().date()
const thisWeek = Array.from({length:7}).map((item,index) = >{
return dayjs().isoWeekday(index + 1).date()
})
console.log(today,thisWeek)
return (<div></div>)}Copy the code
In the above code I introduced dayJS and then defined two variables
Today: today’s date, for example, the 26th
ThisWeek: An array of seven dates for the week
I used array.from ({length:7}) as a method to quickly create an Array of seven lengths. Then I used map to iterate, passing in the index of the iteration through dayJS isoWeek() and getting the date from date()
Gets or sets ISO Day of the Week (opens New Window), where 1 is Monday and 7 is Sunday.
We print out the two variables to see if they are the data we need. The console output is as follows:
Improve the page
We then went on to refine the page and data, and finally finished the component code as follows:
// dayTodo/DatePick.jsx
import React, { useState } from "react"
import { IconButton, Button } from "@mui/material"
import ArrowBackIosNewOutlinedIcon from "@mui/icons-material/ArrowBackIosNewOutlined"
import ArrowForwardIosOutlinedIcon from "@mui/icons-material/ArrowForwardIosOutlined"
import dayjs from "dayjs"
import isoWeek from "dayjs/plugin/isoWeek"
import isToday from "dayjs/plugin/isToday"
import localeData from "dayjs/plugin/localeData"
import "dayjs/locale/zh-cn"
dayjs.locale("zh-cn")
dayjs.extend(isoWeek)
dayjs.extend(isToday)
dayjs.extend(localeData)
export default function DatePicker() {
// The currently selected date
const [activeDate, setDate] = useState(dayjs())
// Check if this is the selected date
const isActive = (item) = > item.date() === activeDate.date()
// An array of date objects for seven days of the week
const thisWeek = Array.from({ length: 7 }).map((item, index) = > {
return dayjs().isoWeekday(index + 1)})return (
<div className=" p-5">
<div className="inline-flex rounded-md bg-gray-100 p-1 items-center ">{/* Flip button */}<IconButton size="small">
<ArrowBackIosNewOutlinedIcon fontSize="12px" />
</IconButton>ThisWeek. Map ((item) => {return () thisWeek.<div
className={`flex items-center justify-center cursor-pointer w-7 h-7 rounded-full mx-1The ${item.date() = = =activeDate.date()
? "bg-primary"
: item.isToday()? "bg-gray-200"
: "hover:bg-gray-200` "}}key={item}
size="small"
onClick={()= > {
setDate(item)
}}
>
<span className="text-sm">{item.isToday() ? "Today" : item.date()}</span>
</div>}} {/* Scroll down button */}<IconButton size="small">
<ArrowForwardIosOutlinedIcon fontSize="12px" />
</IconButton>{/* The selected date corresponds to the day of the week */}<Button variant="text">Activedate.month () + 1} month ${activeDate.date()} day ${activeDate.istoday ()? Activedate.localedata ().weekdays(dayjs(activeDate))} '}</Button>
</div>
</div>)}Copy the code
The effect is as follows:
It took quite a bit of time to finally implement this code, mostly looking through the Dayjs documentation. Here are some of the more complex points:
The main difficulty in style is to determine the current selected time and whether the selected time isToday. I use isToday, a method provided by dayjs, and a method defined by myself
Displaying the day of the week when the currently selected time is in Chinese uses a localized dayJS feature that loads the Chinese package first and then retrieves it based on the currently selected time.
All that’s left to do is switch from last week to next week and a back to today little sun button to complete the time selection bar.
Currently this component is also coupled with a lot of code, in fact date-related data will be needed by many components in the future, and the plug-ins and languages introduced by DayJS should also be removed. I’d like to wait until I introduce a global state management library to pull out uniformly. Redux will be used and encapsulated, and basically pages and temporary data will work
conclusion
The component I wrote today used a lot of styles. In fact, I wanted to introduce a CSS-in-JS library to learn new ideas, but I read the documentation and decided not to introduce it because it wasn’t really necessary.
The difference between VUE and React is noticeable in areas with more styles. When writing a vue, I always worry about tailwindcss being too long and whether I need to separate it from style.
In React, there are almost all styles coupled to JSX, and there is no function to modify component native styles. I don’t know what is the most elegant way to write style in React
Today, when I was writing the code, I was always wondering whether I delayed the progress of learning by writing the code again and again. Besides, the article was not read by many people, so it was necessary to insist.
But woke up after a nap and still opened the Nuggets (probably I still like the feeling that can help others), I sincerely hope that my development ideas or step pit process can help everyone!