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!