0302useState-hooks-react-仿低代碼平臺項目

文章目錄

    • 1 useState
      • 1.1 說明
        • 返回
      • 1.2 示例
      • 1.3 數據類型
    • 2 state
      • 2.1 概述
      • 2.2 state特點
    • 3 state重構問卷
    • 4 immer
    • 結語

1 useState

useState 是一個 React Hook,它允許你向組件添加一個 狀態變量。

1.1 說明

  • 語法
const [state, setState] = useState(initialState)
  • 參數 initialState: 你希望 state 初始化的值。它可以是任何類型的值,但對于函數有特殊的行為。在初始渲染后,此參數將被忽略。
  • 如果傳遞函數作為 initialState,則它將被視為 初始化函數。它應該是純函數,不應該接受任何參數,并且應該返回一個任何類型的值。當初始化組件時,React 將調用你的初始化函數,并將其返回值存儲為初始狀態。
返回

useState 返回一個由兩個值組成的數組:

  1. 當前的 state。在首次渲染時,它將與你傳遞的 initialState 相匹配。
  2. set 函數,它可以讓你將 state 更新為不同的值并觸發重新渲染。

1.2 示例

如下是一個簡單的點擊按鈕累加的示例:

import { useState } from "react";
function Acc() {// 普通js變量無法觸發組件更新// let count = 0;//useState可以觸發組件更新const [count, setCount] = useState(0);// 點擊累加function add() {setCount(count + 1);}return (<><button onClick={add}> click to accumulate:{count} </button></>);
}export default Acc;

普通js變量無法觸發組件更新,如下圖所示:在這里插入圖片描述

使用useState實現頁面組件更新,如下圖所示:在這里插入圖片描述

1.3 數據類型

useState(0)
useState('a')
useState({"a": 1, "b": 2})
useState([1,2,3])
  • xxx類型沒有限制,可以是任意類型

2 state

2.1 概述

組件可以擁有狀態(state),它是組件數據的私有部分,可以用來管理動態數據。

狀態僅適用于類組件,或者使用 React 的 Hook 時可以在函數組件中使用。

React 把組件看成是一個狀態機(State Machines)。通過與用戶的交互,實現不同狀態,然后渲染 UI,讓用戶界面和數據保持一致。

React 里,只需更新組件的 state,然后根據新的 state 重新渲染用戶界面(不要操作 DOM)。

以下實例創建一個名稱擴展為 React.Component 的 ES6 類,在 render() 方法中使用 this.state 來修改當前的時間。

添加一個類構造函數來初始化狀態 this.state,類組件應始終使用 props 調用基礎構造函數。


2.2 state特點

  • State異步更新,示例代碼如下

    import { FC, useState } from "react";
    const StateDemo01: FC = () => {//useState可以觸發組件更新const [count, setCount] = useState(0);const [name, setName] = useState("張三");// 點擊累加function add() {setCount(count + 1);console.log(count);//如果一個變量不用于jsx中顯示,不要用useState管理它,用useRef.setName("李四");}return (<><button onClick={add}> click to accumulate:{count} </button></>);
    };export default StateDemo01;
    

打印結果如下所示:在這里插入圖片描述

  • state可能會被合并,

      // 點擊累加function add() {setCount(count + 1);setCount(count + 1);setCount(count + 1);setCount(count + 1);setCount(count + 1);console.log(count);//如果一個變量不用于jsx中顯示,不要用useState管理它,用useRef.// setName("李四");}
    

    頁面結果如上所示,如果想要不被合并,參數傳入函數,代碼如下:

        setCount((count) => count + 1);
    
  • 不可變數據,如需修改數據,需要傳入新值

    import { FC, useState } from "react";
    const StateDemo02: FC = () => {//useState可以觸發組件更新const [userInfo, setUserInfo] = useState({ name: "張三", age: 20 });// 點擊累加function edit() {// 不可變數據,不去修改state的值,而是傳入一個新的值或者返回一個新值的函數或者表達式// setUserInfo({ name: "張三", age: 21 }); // 全量語法setUserInfo({ ...userInfo, age: 21 }); // 結構語法}return (<><h3>state:不可變數據</h3><div> {JSON.stringify(userInfo)} </div><button onClick={edit}> 修改年齡 </button></>);
    };export default StateDemo02;

    修改數組

    setXxx([...arr, 5])
    setXxx(arr.concat(5))
    

3 state重構問卷

  • state替換文件列表

    import { FC, useState } from "react";import QuestionCard from "./QuestionCard";
    const List2: FC = () => {//列表頁//問卷列表數據const questions = [{ id: "q1", title: "問卷1", isPublished: false },{ id: "q2", title: "問卷2", isPublished: false },{ id: "q3", title: "問卷3", isPublished: true },{ id: "q4", title: "問卷4", isPublished: false },{ id: "q5", title: "問卷5", isPublished: true },];const [questionList, setQuestionList] = useState(questions);const r = Math.random().toString().slice(-3);return (<div><h1>問卷列表頁</h1><div>{questionList.map((q) => {const { id, title, isPublished } = q;return (<QuestionCardkey={id}id={id}title={title}isPublished={isPublished}/>);})}</div></div>);
    };export default List2;
  • 新增問卷

    import { FC, useState } from "react";import QuestionCard from "./QuestionCard";
    const List2: FC = () => {//列表頁//問卷列表數據const questions = [{ id: "q1", title: "問卷1", isPublished: false },{ id: "q2", title: "問卷2", isPublished: false },{ id: "q3", title: "問卷3", isPublished: true },{ id: "q4", title: "問卷4", isPublished: false },{ id: "q5", title: "問卷5", isPublished: true },];const [questionList, setQuestionList] = useState(questions);const r = Math.random().toString().slice(-3);// 新增問卷function add() {setQuestionList([...questionList,{id: "q" + r,title: "問卷" + r,isPublished: false,},]);}return (<div><h1>問卷列表頁</h1><div>{questionList.map((q) => {const { id, title, isPublished } = q;return (<QuestionCardkey={id}id={id}title={title}isPublished={isPublished}/>);})}</div><div><button onClick={add}>新增問卷</button></div></div>);
    };export default List2;
    

    效果如下所示:在這里插入圖片描述

    • 刪除問卷

    List2.tsx代碼如下:

    import { FC, useState } from "react";import QuestionCard from "./components/QuestionCard";
    const List2: FC = () => {//列表頁//問卷列表數據const questions = [{ id: "q1", title: "問卷1", isPublished: false },{ id: "q2", title: "問卷2", isPublished: false },{ id: "q3", title: "問卷3", isPublished: true },{ id: "q4", title: "問卷4", isPublished: false },{ id: "q5", title: "問卷5", isPublished: true },];const [questionList, setQuestionList] = useState(questions);const r = Math.random().toString().slice(-3);// 新增問卷function add() {setQuestionList([...questionList,{id: "q" + r,title: "問卷" + r,isPublished: false,},]);}// 刪除問卷function deleteQuestion(id: string) {setQuestionList(questionList.filter((q) => {return q.id !== id;}));}return (<div><h1>問卷列表頁</h1><div>{questionList.map((q) => {const { id, title, isPublished } = q;return (<QuestionCardkey={id}id={id}title={title}isPublished={isPublished}deleteQuestion={deleteQuestion}/>);})}</div><div><button onClick={add}>新增問卷</button></div></div>);
    };export default List2;
    

    QuestionCard.tsx代碼如下:

    import React, { FC } from "react";import "./QuestionCard.css";type PropsType = {id: string;title: string;isPublished: boolean;deleteQuestion: (id: string) => void;
    };const QuestionCard: FC<PropsType> = (props) => {const { id, title, isPublished, deleteQuestion } = props;//編輯問卷function edit(id: string) {console.log("id:", id);}// 刪除問卷function del(id: string) {deleteQuestion(id);}return (<div key={id} className="list-item"><strong>{title}</strong>&nbsp;{/* 條件判斷 */}{isPublished ? (<span style={{ color: "green" }}>已發布</span>) : (<span>未發布 </span>)}&nbsp;<button onClick={() => edit(id)}>編輯問卷</button>&nbsp;<button onClick={() => del(id)}>刪除問卷</button></div>);
    };export default QuestionCard;
    

    頁面效果如下圖所示:在這里插入圖片描述

  • 發布問卷

List2.tsx代碼如下:

import { FC, useState } from "react";import QuestionCard from "./components/QuestionCard";
const List2: FC = () => {//列表頁//問卷列表數據const questions = [{ id: "q1", title: "問卷1", isPublished: false },{ id: "q2", title: "問卷2", isPublished: false },{ id: "q3", title: "問卷3", isPublished: true },{ id: "q4", title: "問卷4", isPublished: false },{ id: "q5", title: "問卷5", isPublished: true },];const [questionList, setQuestionList] = useState(questions);const r = Math.random().toString().slice(-3);// 新增問卷function add() {setQuestionList([...questionList,{id: "q" + r,title: "問卷" + r,isPublished: false,},]);}// 刪除問卷function deleteQuestion(id: string) {setQuestionList(questionList.filter((q) => {return q.id !== id;}));}// 刪除問卷function publishQuestion(id: string) {setQuestionList(questionList.map((q) => {if (q.id !== id) {return q;}return {...q,isPublished: true,};}));}return (<div><h1>問卷列表頁</h1><div>{questionList.map((q) => {const { id, title, isPublished } = q;return (<QuestionCardkey={id}id={id}title={title}isPublished={isPublished}deleteQuestion={deleteQuestion}publishQuestion={publishQuestion}/>);})}</div><div><button onClick={add}>新增問卷</button></div></div>);
};export default List2;

QuestionCard.tsx代碼如下:

import React, { FC } from "react";import "./QuestionCard.css";type PropsType = {id: string;title: string;isPublished: boolean;deleteQuestion?: (id: string) => void;publishQuestion?: (id: string) => void;
};const QuestionCard: FC<PropsType> = (props) => {const { id, title, isPublished, deleteQuestion, publishQuestion } = props;//編輯問卷function edit(id: string) {console.log("id:", id);}// 刪除問卷function del(id: string) {deleteQuestion && deleteQuestion(id);}// 發布問卷function publish(id: string) {publishQuestion && publishQuestion(id);}return (<div key={id} className="list-item"><strong>{title}</strong>&nbsp;{/* 條件判斷 */}{isPublished ? (<span style={{ color: "green" }}>已發布</span>) : (<span>未發布 </span>)}&nbsp;<button onClick={() => edit(id)}>編輯問卷</button>&nbsp;<button onClick={() => del(id)}>刪除問卷</button>&nbsp;<button onClick={() => publish(id)}>發布問卷</button></div>);
};export default QuestionCard;

4 immer

如果你的 state 有多層的嵌套,你或許應該考慮 將其扁平化。但是,如果你不想改變 state 的數據結構,你可能更喜歡用一種更便捷的方式來實現嵌套展開的效果。Immer 是一個非常流行的庫,它可以讓你使用簡便但可以直接修改的語法編寫代碼,并會幫你處理好復制的過程。通過使用 Immer,你寫出的代碼看起來就像是你“打破了規則”而直接修改了對象:

immer的使用說明參考下面連接2,這里用immer重構問卷,List2.tsx代碼如下:

import { FC, useState } from "react";
import { useImmer } from "use-immer";import QuestionCard from "./components/QuestionCard";
const List2: FC = () => {//列表頁//問卷列表數據const questions = [{ id: "q1", title: "問卷1", isPublished: false },{ id: "q2", title: "問卷2", isPublished: false },{ id: "q3", title: "問卷3", isPublished: true },{ id: "q4", title: "問卷4", isPublished: false },{ id: "q5", title: "問卷5", isPublished: true },];const [questionList, updateQuestionList] = useImmer(questions);const r = Math.random().toString().slice(-3);// 新增問卷function add() {updateQuestionList((draft) => {draft.push({id: "q" + r,title: "問卷" + r,isPublished: false,});});}// 刪除問卷function deleteQuestion(id: string) {updateQuestionList((draft) => {const index = draft.findIndex((q) => q.id === id);draft.splice(index, 1);});}// 發布問卷function publishQuestion(id: string) {updateQuestionList((draft) => {const q = draft.find((q) => q.id === id);q && (q.isPublished = true);});}return (<div><h1>問卷列表頁</h1><div>{questionList.map((q) => {const { id, title, isPublished } = q;return (<QuestionCardkey={id}id={id}title={title}isPublished={isPublished}deleteQuestion={deleteQuestion}publishQuestion={publishQuestion}/>);})}</div><div><button onClick={add}>新增問卷</button></div></div>);
};export default List2;

結語

?QQ:806797785

??倉庫地址:https://gitee.com/gaogzhen

??倉庫地址:https://github.com/gaogzhen

[1]useState[CP/OL].

[2]使用 Immer 編寫簡潔的更新邏輯[CP/OL].

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/74766.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74766.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74766.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端實現單點登錄(SSO)的方案

概念&#xff1a;單點登錄&#xff08;Single Sign-On, SSO&#xff09;主要是在多個系統、多個瀏覽器或多個標簽頁之間共享登錄狀態&#xff0c;保證用戶只需登錄一次&#xff0c;就能訪問多個關聯應用&#xff0c;而不需要重復登錄。 &#x1f4a1; 方案分類 1. 前端級別 SS…

zabbix監控網站(nginx、redis、mysql)

目錄 前提準備&#xff1a; zabbix-server主機配置&#xff1a; 1. 安裝數據庫 nginx主機配置&#xff1a; 1. 安裝nginx redis主機配置&#xff1a; 1. 安裝redis mysql主機配置&#xff1a; 1. 安裝數據庫 zabbix-server&#xff1a; 1. 安裝zabbix 2. 編輯配置文…

無人機等非合作目標公開數據集2025.4.3

一.無人機遙感數據概述 1.1 定義與特點 在遙感技術的不斷發展中&#xff0c;無人機遙感數據作為一種新興的數據源&#xff0c;正逐漸嶄露頭角。它是通過無人駕駛飛行器&#xff08;UAV&#xff09;搭載各種傳感器獲取的地理空間信息&#xff0c;具有 覆蓋范圍大、綜合精度高、…

大數據時代的隱私保護:區塊鏈技術的創新應用

一、引言 在當今數字化時代&#xff0c;大數據已經成為推動社會發展的關鍵力量。從商業決策到社會治理&#xff0c;從醫療健康到金融服務&#xff0c;數據的價值日益凸顯。然而&#xff0c;隨著數據的大量收集和廣泛使用&#xff0c;隱私保護問題也日益突出。如何在充分利用大…

LeetCode 2442:統計反轉后的不同整數數量

目錄 核心思想&#xff1a;數字的“拆分”與“重組” 分步拆解&#xff08;以輸入 123 為例&#xff09; 關鍵操作詳解 為什么能處理中間或末尾的0&#xff1f; 數學本質 總結 題目描述 解題思路 代碼實現 代碼解析 復雜度分析 示例演示 總結 核心思想&#xff1a;…

Python爬蟲第3節-會話、Cookies及代理的基本原理

目錄 一、會話和Cookies 1.1 靜態網頁和動態網頁 1.2 無狀態HTTP 1.3 常見誤區 二、代理的基本原理 2.1 基本原理 2.2 代理的作用 2.3 爬蟲代理 2.4 代理分類 2.5 常見代理設置 一、會話和Cookies 大家在瀏覽網站過程中&#xff0c;肯定經常遇到需要登錄的場景。有些…

Flutter項目之登錄注冊功能實現

目錄&#xff1a; 1、頁面效果2、登錄兩種狀態界面3、中間按鈕部分4、廣告區域5、最新資訊6、登錄注冊頁聯調6.1、網絡請求工具類6.2、注冊頁聯調6.3、登錄問題分析6.4、本地緩存6.5、共享token6.6、登錄頁聯調6.7、退出登錄 1、頁面效果 import package:flutter/material.dart…

木馬學習記錄

一句話木馬是什么 一句話木馬就是僅需要一行代碼的木馬&#xff0c;很簡短且簡單&#xff0c;木馬的函數將會執行我們發送的命令 如何發送命令&#xff06;發送的命令如何執行? 有三種方式&#xff1a;GET&#xff0c;POST&#xff0c;COOKIE&#xff0c;一句話木馬中用$_G…

(C語言)單鏈表(1.0)(單鏈表教程)(數據結構,指針)

目錄 1. 什么是單鏈表&#xff1f; 2. 單鏈表的代碼表示 3. 單鏈表的基本操作 3.1 初始化鏈表 3.2 插入結點&#xff08;頭插法&#xff09; 3.3 插入結點&#xff08;尾插法&#xff09; 3.4 遍歷鏈表 4. 單鏈表的優缺點 代碼&#xff1a;*L(LinkList)malloc(sizeof(…

Sentinel-自定義資源實現流控和異常處理

目錄 使用SphU的API實現自定義資源 BlockException 使用SentinelResource注解定義資源 SentinelResourceAspect 使用Sentinel實現限流降級等效果通常需要先把需要保護的資源定義好&#xff0c;之后再基于定義好的資源為其配置限流降級等規則。 Sentinel對于主流框架&#…

Linux信號處理解析:從入門到實戰

Linux信號處理全解析&#xff1a;從入門到實戰 一、初識Linux信號&#xff1a;系統級的"緊急電話" 信號是什么&#xff1f; 信號是Linux系統中進程間通信的"緊急通知"&#xff0c;如同現實中的交通信號燈。當用戶按下CtrlC&#xff08;產生SIGINT信號&…

Java的Selenium的特殊元素操作與定位之select下拉框

如果頁面元素是一個下拉框&#xff0c;我們可以將此web元素封裝為Select對象 Select selectnew Select(WebElement element); Select對象常用api select.getOptions();//獲取所有選項select.selectBylndex(index);//根據索引選中對應的元素select.selectByValue(value);//選…

藍橋云客 刷題統計

刷題統計 問題描述 小明決定從下周一開始努力刷題準備藍橋杯競賽。他計劃周一至周五每天做 a 道題目&#xff0c;周六和周日每天做 b 道題目。請你幫小明計算&#xff0c;按照計劃他將在第幾天實現做題數大于等于 n 題&#xff1f; 輸入格式 輸入一行包含三個整數 a, b 和 …

三防筆記本有什么用 | 三防筆記本有什么特別

在現代社會&#xff0c;隨著科技的不斷進步&#xff0c;筆記本電腦已經成為人們工作和生活的重要工具。然而&#xff0c;在一些特殊的工作環境和極端條件下&#xff0c;普通筆記本電腦往往難以滿足需求。這時&#xff0c;三防筆記本以其獨特的設計和卓越的性能&#xff0c;成為…

智能體和RPA都需要程序思維,如何使用影刀的變量?

歡迎來到濤濤聊AI&#xff0c; 不管AI還是RPA&#xff0c;都需要用到編程思想才能完成批量工作。今天研究了下影刀的變量。 變量類型 根據變量值選擇相應的類型&#xff0c;可選擇任意一種影刀所支持的數據類型 變量值 指定變量中保存的值&#xff0c;會根據不同的類型設置…

【藍橋杯】算法筆記3

1. 最長上升子序列(LIS) 1.1. 題目 想象你有一排數字,比如:3, 1, 2, 1, 8, 5, 6 你要從中挑出一些數字,這些數字要滿足兩個條件: 你挑的數字的順序要和原來序列中的順序一致(不能打亂順序) 你挑的數字要一個比一個大(嚴格遞增) 問:最多能挑出多少個這樣的數字? …

性能測試之jmeter的基本使用

簡介 Jmeter是Apache的開源項目&#xff0c;基于Java開發&#xff0c;主要用于進行壓力測試。 優點&#xff1a;開源免費、支持多協議、輕量級、功能強大 官網&#xff1a;https://jmeter.apache.org/index.html 安裝 安裝步驟&#xff1a; 下載&#xff1a;進入jmeter的…

【NLP 面經 7、常見transformer面試題】

目錄 1. 為何使用多頭注意力機制&#xff1f; 2. Q和K使用不同權重矩陣的原因 3. 選擇點乘而非加法的原因 4. Attention進行scaled的原因 5. 對padding做mask操作 6. 多頭注意力降維原因 7. Transformer Encoder模塊簡介 8. 乘以embedding size的開方的意義 9. 位置編碼 10. 其…

【深度學習】CNN簡述

文章目錄 一、卷積神經網絡&#xff08;CNN&#xff09;二、CNN結構特性1. CNN 典型結構2. 局部連接3. 權重共享4.空間或時間上的次采樣 三、理解層面 一、卷積神經網絡&#xff08;CNN&#xff09; 卷積神經網絡(Convolutional Neural Network&#xff0c;CNN)是一種用于處理…

理解OSPF 特殊區域NSSA和各類LSA特點

本文基于上文 理解OSPF Stub區域和各類LSA特點 在理解了Stub區域之后&#xff0c;我們再來理解一下NSSA區域&#xff0c;NSSA區域用于需要引入少量外部路由&#xff0c;同時又需要保持Stub區域特性的情況 一、 網絡總拓撲圖 我們在R1上配置黑洞路由&#xff0c;來模擬NSSA區域…