React learning notes of 1

Advantages of React:

  Virtual DOM:

  React defines a variable-based model for the DOM, which means all operations and transformations happen within these variables. This reduces the number of direct manipulations on the real DOM, leading to improved performance.

  Component System:

   React's component system allows you to treat any part of a page or application as a reusable component. This leads to a more modular structure with low coupling and high cohesion.

Single-Way Data Flow:

The core concept of single-way data flow simplifies the data binding process. You only need to bind server-side data to the frontend, allowing developers to focus on business logic rather than complex data management.

JSX:

React allows you to use HTML-like syntax in your JavaScript code. JSX makes it easier to write and understand the structure of components.

Simplicity and Reusability:

Function components in React are simple and easy to understand, making them ideal for beginners. They also offer great reusability, reducing the amount of code that needs to be written.

Performance Optimization:

Function components have better rendering performance compared to class components. They consume less memory and CPU resources because they don't create component instances and avoid unnecessary lifecycle methods.

Testability:

Function components are typically stateless and act like pure functions, which makes them easier to test.

Hooks:

React function components support Hooks, which were introduced in React 16.8. Hooks enable function components to manage state and lifecycle without the need for class components, enhancing their functionality and flexibility.

What is JSX?

JSX stands for JavaScript and XML (HTML), representing the way of writing HTML template structures within JS code. It is the method used in React for building UI components.

  • This is a react template code for basic.

const message = 'hello,world'

function App(){
  return (
    <div>
      <h1>this is title</h1>
      {message}
    </div>
  )
}

Js Expression

const message = 'hello,world'

function getAge(){
  return 18
}

function App(){
  return (
    <div>
      <h1>this is title</h1>
      {/* string */}
      {'this is str'}
      {/* variable */}
      {message}
      {/* function */}
      {getAge()}
    </div>
  )
}

List rendering

const list = [
  {id:1, name:'Java'},
  {id:2, name: 'C#'},
  {id:3, name: 'React'},
  {id:4, name: 'Rust'}
]

function App(){
  return (
    <ul>
      {list.map(item=><li key={item.id}>{item}</li>)}
    </ul>
  )
}

Conditional rendering

In React, you can use logic with the operator &&, ternary expressions (? 🙂 Implements basic conditional rendering

const flag = true
const loading = false

function App(){
  return (
    <>
      {flag && <span>this is span</span>}
      {loading ? <span>loading...</span>:<span>this is span</span>}
    </>
  )
}

React Event Bind

React Event Binds through on + eventName={event function}, follow the camel naming method.

function App(){
  const clickHandler = (e)=>{
    console.log('button has clicked', e)
  }
  return (
    <button onClick={clickHandler}>click me</button>
  )
}

Passing Custom Parameters

Event arguments e and custom arguments are passed at the location of the event binding, and the parameters are declared in clickHandler, in the corresponding order

function App(){
  const clickHandler = (name,e)=>{
    console.log('button has clicked', name,e)
  }
  return (
    <button onClick={(e)=>clickHandler('jack',e)}>click me</button>
  )
}

React Components

A component is a part of a user interface, it can have its own logic and appearance, components can be nested with each other, and can be used multiple times

How to use the components

function Button(){
  return <button>click me</button>
}

function App(){
  return (
    <div>
      <Button/>
      <Button></Button>
    </div>
  )
}

Components Status

useState is a React Hook (function) that allows us to add a 'state variable' to a component to control the rendering results that affect the component

function App(){
  const [ count, setCount ] = React.useState(0)
  return (
    <div>
      <button onClick={()=>setCount(count+1)}>{ count }</button>
    </div>
  )
}

example of simple comment list

todo:

  • display comment list
  • delete comment
  • hight tab for navigate
  • set comment can order by hot or date

base code

import { useState } from 'react'
import './App.scss'
import avatar from './images/bozai.png'

// comment list data
const defaultList = [
  {
    rpid: 3,
    user: {
      uid: '13258165',
      avatar: 'https://www.coderlk.com/wp-content/uploads/2024/08/dulante.png',
      uname: 'Durante',
    },
    content: 'ok, good job',
    ctime: '10-18 08:15',
    like: 88,
  },
  {
    rpid: 2,
    user: {
      uid: '36080105',
      avatar: '',
      uname: '',
    },
    content: 'Almost every wise saying has an opposite one,no less wise,to balance it.',
    ctime: '12-13 11:29',
    like: 93,
  },
  {
    rpid: 1,
    user: {
      uid: '30009257',
      avatar,
      uname: 'lk',
    },
    content: 'To write the most elegant code',
    ctime: '11-19 09:00',
    like: 66,
  },
]

const user = {
  uid: '30009257',
  avatar,
  uname: 'lk
}

const tabs = [
  { type: 'hot', text: 'Hot'},
  { type: 'time', text: 'News'}
]

const App = () => {
  return (
    <div className="app">
      <div className="reply-navigation">
        <ul className="nav-bar">
          <li className="nav-title">
            <span className="nav-title-text">comment</span>
            <span className="total-reply">{10}</span>
          </li>
          <li className="nav-sort">
            <span className='nav-item'>Hot</span>
            <span className='nav-item'>News</span>
          </li>
        </ul>
      </div>

      <div className="reply-wrap">
        <div className="box-normal">
          <div className="reply-box-avatar">
            <div className="bili-avatar">
              <img className="bili-avatar-img" src={avatar} alt="user avatar" />
            </div>
          </div>
          <div className="reply-box-wrap">
            <textarea
              className="reply-box-textarea"
              placeholder="place a friendly comment"
            />
            <div className="reply-box-send">
              <div className="send-text">publish</div>
            </div>
          </div>
        </div>
        <div className="reply-list">
          <div className="reply-item">
            <div className="root-reply-avatar">
              <div className="bili-avatar">
                <img
                  className="bili-avatar-img" alt=""
                />
              </div>
            </div>

            <div className="content-wrap">
              <div className="user-info">
                <div className="user-name">jack</div>
              </div>
              <div className="root-reply">
                <span className="reply-content">this is comment repaied</span>
                <div className="reply-info">
                  <span className="reply-time">{'2023-11-11'}</span>
                  <span className="reply-time">likes:{100}</span>
                  <span className="delete-btn">
                    delete
                  </span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export default App

CSS configure

.app {
  width: 80%;
  margin: 50px auto;
}

.reply-navigation {
  margin-bottom: 22px;

  .nav-bar {
    display: flex;
    align-items: center;
    margin: 0;
    padding: 0;
    list-style: none;

    .nav-title {
      display: flex;
      align-items: center;
      width: 114px;
      font-size: 20px;

      .nav-title-text {
        color: #18191c;
        font-weight: 500;
      }
      .total-reply {
        margin: 0 36px 0 6px;
        color: #9499a0;
        font-weight: normal;
        font-size: 13px;
      }
    }

    .nav-sort {
      display: flex;
      align-items: center;
      color: #9499a0;
      font-size: 13px;

      .nav-item {
        cursor: pointer;

        &:hover {
          color: #00aeec;
        }

        &:last-child::after {
          display: none;
        }
        &::after {
          content: ' ';
          display: inline-block;
          height: 10px;
          width: 1px;
          margin: -1px 12px;
          background-color: #9499a0;
        }
      }

      .nav-item.active {
        color: #18191c;
      }
    }
  }
}

.reply-wrap {
  position: relative;
}
.box-normal {
  display: flex;
  transition: 0.2s;

  .reply-box-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 80px;
    height: 50px;
  }

  .reply-box-wrap {
    display: flex;
    position: relative;
    flex: 1;

    .reply-box-textarea {
      width: 100%;
      height: 50px;
      padding: 5px 10px;
      box-sizing: border-box;
      color: #181931;
      font-family: inherit;
      line-height: 38px;
      background-color: #f1f2f3;
      border: 1px solid #f1f2f3;
      border-radius: 6px;
      outline: none;
      resize: none;
      transition: 0.2s;

      &::placeholder {
        color: #9499a0;
        font-size: 12px;
      }
      &:focus {
        height: 60px;
        background-color: #fff;
        border-color: #c9ccd0;
      }
    }
  }

  .reply-box-send {
    position: relative;
    display: flex;
    flex-basis: 86px;
    align-items: center;
    justify-content: center;
    margin-left: 10px;
    border-radius: 4px;
    cursor: pointer;
    transition: 0.2s;

    & .send-text {
      position: absolute;
      z-index: 1;
      color: #fff;
      font-size: 16px;
    }
    &::after {
      position: absolute;
      width: 100%;
      height: 100%;
      background-color: #00aeec;
      border-radius: 4px;
      opacity: 0.5;
      content: '';
    }
    &:hover::after {
      opacity: 1;
    }
  }
}
.bili-avatar {
  position: relative;
  display: block;
  width: 48px;
  height: 48px;
  margin: 0;
  padding: 0;
  border-radius: 50%;
}
.bili-avatar-img {
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  width: 48px;
  height: 48px;
  object-fit: cover;
  border: none;
  border-radius: 50%;
  image-rendering: -webkit-optimize-contrast;
  transform: translate(-50%, -50%);
}

// 评论列表
.reply-list {
  margin-top: 14px;
}
.reply-item {
  padding: 22px 0 0 80px;
  .root-reply-avatar {
    position: absolute;
    left: 0;
    display: flex;
    justify-content: center;
    width: 80px;
    cursor: pointer;
  }

  .content-wrap {
    position: relative;
    flex: 1;

    &::after {
      content: ' ';
      display: block;
      height: 1px;
      width: 100%;
      margin-top: 14px;
      background-color: #e3e5e7;
    }

    .user-info {
      display: flex;
      align-items: center;
      margin-bottom: 4px;

      .user-name {
        height: 30px;
        margin-right: 5px;
        color: #61666d;
        font-size: 13px;
        line-height: 30px;
        cursor: pointer;
      }
    }

    .root-reply {
      position: relative;
      padding: 2px 0;
      color: #181931;
      font-size: 15px;
      line-height: 24px;
      .reply-info {
        position: relative;
        display: flex;
        align-items: center;
        margin-top: 2px;
        color: #9499a0;
        font-size: 13px;

        .reply-time {
          width: 76px;
          margin-right: 20px;
        }
        .reply-like {
          display: flex;
          align-items: center;
          margin-right: 19px;

          .like-icon {
            width: 14px;
            height: 14px;
            margin-right: 5px;
            color: #9499a0;
            background-position: -153px -25px;
            &:hover {
              background-position: -218px -25px;
            }
          }
          .like-icon.liked {
            background-position: -154px -89px;
          }
        }
        .reply-dislike {
          display: flex;
          align-items: center;
          margin-right: 19px;
          .dislike-icon {
            width: 16px;
            height: 16px;
            background-position: -153px -153px;
            &:hover {
              background-position: -217px -153px;
            }
          }
          .dislike-icon.disliked {
            background-position: -154px -217px;
          }
        }
        .delete-btn {
          cursor: pointer;
          &:hover {
            color: #00aeec;
          }
        }
      }
    }
  }
}

.reply-none {
  height: 64px;
  margin-bottom: 80px;
  color: #99a2aa;
  font-size: 13px;
  line-height: 64px;
  text-align: center;
}

set function

 const [activeTab, setActiveTab] = useState('hot')
  const [list, setList] = useState(defaultList)
  const onDelete = rpid => {
    setList(list.filter(item => item.rpid !== rpid))
  }

  const onToggle = type => {
    setActiveTab(type)
    let newList
    if (type === 'time') {
      newList = orderBy(list, 'ctime', 'desc')
    } else {
      newList = orderBy(list, 'like', 'desc')
    }
    setList(newList)
  }

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注