国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【實(shí)戰(zhàn)】三、TS 應(yīng)用:JS神助攻 - 強(qiáng)類(lèi)型 —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級(jí)項(xiàng)目(三)

這篇具有很好參考價(jià)值的文章主要介紹了【實(shí)戰(zhàn)】三、TS 應(yīng)用:JS神助攻 - 強(qiáng)類(lèi)型 —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級(jí)項(xiàng)目(三)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。


學(xué)習(xí)內(nèi)容來(lái)源:React + React Hook + TS 最佳實(shí)踐-慕課網(wǎng)


相對(duì)原教程,我在學(xué)習(xí)開(kāi)始時(shí)(2023.03)采用的是當(dāng)前最新版本:

項(xiàng) 版本
react & react-dom ^18.2.0
react-router & react-router-dom ^6.11.2
antd ^4.24.8
@commitlint/cli & @commitlint/config-conventional ^17.4.4
eslint-config-prettier ^8.6.0
husky ^8.0.3
lint-staged ^13.1.2
prettier 2.8.4
json-server 0.17.2
craco-less ^2.0.0
@craco/craco ^7.1.0
qs ^6.11.0
dayjs ^1.11.7
react-helmet ^6.1.0
@types/react-helmet ^6.1.6
react-query ^6.1.0
@welldone-software/why-did-you-render ^7.0.1
@emotion/react & @emotion/styled ^11.10.6

具體配置、操作和內(nèi)容會(huì)有差異,“坑”也會(huì)有所不同。。。


一、項(xiàng)目起航:項(xiàng)目初始化與配置

  • 【實(shí)戰(zhàn)】 一、項(xiàng)目起航:項(xiàng)目初始化與配置 —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級(jí)項(xiàng)目(一)

二、React 與 Hook 應(yīng)用:實(shí)現(xiàn)項(xiàng)目列表

  • 【實(shí)戰(zhàn)】 二、React 與 Hook 應(yīng)用:實(shí)現(xiàn)項(xiàng)目列表 —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級(jí)項(xiàng)目(二)

三、TS 應(yīng)用:JS神助攻 - 強(qiáng)類(lèi)型

1.TS 的必要性

作為正常人,我們?cè)陂_(kāi)發(fā)過(guò)程中難免會(huì)犯以下錯(cuò)誤:

  • 變量名寫(xiě)錯(cuò)
  • 參數(shù)少傳、多傳
  • 數(shù)組或?qū)ο笞兞繉哟闻e(cuò)

相對(duì) JS 在運(yùn)行時(shí)(runtime)才會(huì)發(fā)現(xiàn)錯(cuò)誤,TS 可以幫助我們?cè)?靜態(tài)代碼 中及時(shí)定位錯(cuò)誤,將 弱類(lèi)型JS 轉(zhuǎn)為 強(qiáng)類(lèi)型TS 能夠極大地降低我們編碼過(guò)程中的誤碼率

2.代碼更改

將項(xiàng)目中 srcjs 文件后綴改為 tsjsx 文件后綴改為 tsx,并對(duì)文件代碼做如下修改:

  • 有參數(shù)的組件使用 interface 聲明參數(shù)類(lèi)型
  • 公用類(lèi)型的可以導(dǎo)出+引入
  • 不明確類(lèi)型的顯性賦予 unknow 類(lèi)型 (嚴(yán)格版 any)
  • 不確定參數(shù)是否會(huì)傳的使用 ?: 賦予類(lèi)型
  • 用泛型來(lái)規(guī)范類(lèi)型

更多 ts 知識(shí)學(xué)習(xí)可見(jiàn):【筆記】TS入門(mén)

更改后的文件如下:

  • src\utils\index.ts
import { useEffect, useState } from "react";

export const isFalsy = (val: unknown) => (val === 0 ? false : !val);

// 在函數(shù)里,不可用直接賦值的方式改變傳入的引用類(lèi)型變量
export const cleanObject = (obj: object) => {
  const res = { ...obj };
  Object.keys(res).forEach((key) => {
    //@ts-ignore
    const val = res[key];
    if (isFalsy(val)) {
      //@ts-ignore
      delete res[key];
    }
  });
  return res;
};

export const useMount = (cbk: () => void) => useEffect(() => cbk(), []);

/**
 * @param { 值 } val
 * @param { 延時(shí):默認(rèn) 1000 } delay
 * @returns 在某段時(shí)間內(nèi)多次變動(dòng)后最終拿到的值(delay 延遲的是存儲(chǔ)在隊(duì)列中的上一次變化)
 */
export const useDebounce = <V>(val: V, delay: number = 1000) => {
  // V 泛型,表示傳入與返回類(lèi)型相同
  const [tempVal, setTempVal] = useState(val);

  useEffect(() => {
    // 每次在 val 變化后,設(shè)置一個(gè)定時(shí)器
    const timeout = setTimeout(() => setTempVal(val), delay);
    // 每次在上一個(gè) useEffect 處理完以后再運(yùn)行(useEffect 的天然功能即是在運(yùn)行結(jié)束的 return 函數(shù)中清除上一個(gè)(同一) useEffect)
    return () => clearTimeout(timeout);
  }, [val, delay]);

  return tempVal;
};
  • src\screens\ProjectList\index.jsx
import { SearchPanel } from "./components/SearchPanel";
import { List } from "./components/List";
import { useEffect, useState } from "react";
import { cleanObject, useDebounce, useMount } from "utils";
import * as qs from "qs";

const apiUrl = process.env.REACT_APP_API_URL;

export const ProjectListScreen = () => {
  const [users, setUsers] = useState([]);
  const [param, setParam] = useState({
    name: "",
    personId: "",
  });
  // 對(duì) param 進(jìn)行防抖處理
  const lastParam = useDebounce(param);
  const [list, setList] = useState([]);

  useEffect(() => {
    fetch(
      // name=${param.name}&personId=${param.personId}
      `${apiUrl}/projects?${qs.stringify(cleanObject(lastParam))}`
    ).then(async (res) => {
      if (res.ok) {
        setList(await res.json());
      }
    });
  }, [lastParam]);

  useMount(() => {
    fetch(`${apiUrl}/users`).then(async (res) => {
      if (res.ok) {
        setUsers(await res.json());
      }
    });
  });

  return (
    <div>
      <SearchPanel users={users} param={param} setParam={setParam} />
      <List users={users} list={list} />
    </div>
  );
};

  • src\screens\ProjectList\components\List.jsx
import { User } from "./SearchPanel";

interface Project {
  id: string;
  name: string;
  personId: string;
  star: boolean;
  organization: string;
}
interface ListProps {
  users: User[];
  list: Project[];
}

export const List = ({ users, list }: ListProps) => {
  return (
    <table>
      <thead>
        <tr>
          <th>名稱</th>
          <th>負(fù)責(zé)人</th>
        </tr>
      </thead>
      <tbody>
        {list.map((project) => (
          <tr key={project.id}>
            <td>{project.name}</td>
            {/* undefined.name */}
            <td>
              {users.find((user) => user.id === project.personId)?.name ||
                "未知"}
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
};
  • src\screens\ProjectList\components\SearchPanel.jsx
export interface User {
  id: string;
  name: string;
  email: string;
  title: string;
  organization: string;
}
interface SearchPanelProps {
  users: User[];
  param: {
    name: string;
    personId: string;
  };
  setParam: (param: SearchPanelProps["param"]) => void;
}

export const SearchPanel = ({ users, param, setParam }: SearchPanelProps) => {
  return (
    <form>
      <div>
        {/* setParam(Object.assign({}, param, { name: evt.target.value })) */}
        <input
          type="text"
          value={param.name}
          onChange={(evt) =>
            setParam({
              ...param,
              name: evt.target.value,
            })
          }
        />
        <select
          value={param.personId}
          onChange={(evt) =>
            setParam({
              ...param,
              personId: evt.target.value,
            })
          }
        >
          <option value="">負(fù)責(zé)人</option>
          {users.map((user) => (
            <option key={user.id} value={user.id}>
              {user.name}
            </option>
          ))}
        </select>
      </div>
    </form>
  );
};
  • src\App.tsx
import "./App.css";
import { ProjectListScreen } from "screens/ProjectList";

function App() {
  return (
    <div className="App">
      <ProjectListScreen />
    </div>
  );
}

export default App;

拓展學(xué)習(xí):

  • 【筆記】TS 泛型
  • 【實(shí)戰(zhàn)】用 Custom Hook + TS泛型實(shí)現(xiàn) useArray

部分引用筆記還在草稿階段,敬請(qǐng)期待。。。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-511687.html

到了這里,關(guān)于【實(shí)戰(zhàn)】三、TS 應(yīng)用:JS神助攻 - 強(qiáng)類(lèi)型 —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級(jí)項(xiàng)目(三)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包