lesson02_React知识回顾

创建ts编写的react的项目

npx create-react-app react-typescript --template typescript

npx是什么?

  • 避免安装全局模块,运行且不进行全局安装,下载到临时目录后再删除
  • 调用项目内部的模块,egmocha只在项目中使用,而未全局安装,可以使用node_modules/.bin/mocha --version,也可使用npx mocha --version
import React from "react";

// 传参和接收参数的时候都会接收提醒
interface IHelloProps {
	message: string;
}

const Hello = (props: IHelloProps) => {
	return <h2>{props.message}</h2>
}

export default Hello;

使用react内部定义的类型进行优化

type React.FC<P = {}> = React.FunctionComponent<P>
import React from "react";

// 传参和接收参数的时候都会接收提醒
interface IHelloProps {
	message?: string;
}

const Hello: React.FC<IHelloProps> = (props) => {
	return <h2>{props.message}</h2>
}

Hello.defaultProps = {
	message: "Hello World"
}

export default Hello;

01. useState

version 01 – useState基本使用

import React, {useState} from "react";

const LikeButton: React.FC = () => {
	const [like, setLike] = useState(0);
	return (
		<button onClick={() => {setLike(like + 1)}}>
			{like}
		</button>
	)
}

export default LikeButton;

version 02 – 用setState包裹对象

import React, {useState} from "react";

const LikeButton: React.FC = () => {
	const [obj, setObj] = useState({like: 0, on: true});
	return (
		<button onClick={() => {setObj({like: obj.like + 1, on: !obj.on})}}>
			{obj.like}
			{obj.on ? "ON" : "OFF"}
		</button>
	)
}

export default LikeButton;

version 03 – 基础变量分开,分别用useState包裹

import React, {useState} from "react";

const LikeButton: React.FC = () => {
	const [like, setLike] = useState(0);
	const [on, setOn] = useState(false);
	return (
		<>
			<button onClick={() => {setLike(like + 1)}}>
				{like}
			</button>
			<button onClick={() => {setOn(!on)}}>
				{on ? "ON" : "OFF"}
			</button>
		</>
	)
}

export default LikeButton;

02. useEffect副作用函数

  • 无需清除的Effect
    第一次渲染和每次渲染之后都会执行
  • 需要清除的Effect
import React, {useEffect} from React;

const MouseTracker: React.FC = () => {
	const [position, setPosition] = useState({x: 0, y: 0});
	useEffect(() => {
		const updateMouse = (e: MouseEvent) => {
			setPosition({x: e.clientX, y: e.clientY});
		}
		document.addEventListener("click", updateMouse);
		return () => {
			document.removeEventListener("click", updateMouse);
		}
	})
	return (
		<p>X: {position.x}, Y: {position.y}</p>
	)
}

export default MouseTracker;

自定义hook重构MouseTracker组件

useMousePosition.tsx文件结构

import React, {useEffect} from React;

// 1. 函数名称必须以use开头
// 2. 多个组件调用,state是隔离的,不会互相影响
const useMousePosition = () => {
	const [position, setPosition] = useState({x: 0, y: 0});
	useEffect(() => {
		const updateMouse = (e: MouseEvent) => {
			setPosition({x: e.clientX, y: e.clientY});
		}
		document.addEventListener("click", updateMouse);
		return () => {
			document.removeEventListener("click", updateMouse);
		}
	}, []);
	return position;
}

export default useMousePosition;

MouseTracker.tsx文件结构

import React, {useEffect} from React;
import useMousePosition from ".hooks//useMousePosition";

const MouseTracker: React.FC = () => {
	const position = useMousePosition();
	return (
		<p>X: {position.x}, Y: {position.y}</p>
	)
}

export default MouseTracker;

自定义URLLoder

  • 提取组件公共操作部分
  • hook得是一个函数
  • hook的返回值是组件需要的
  • hook中的state多个组件不共享

useURLLoader.tsx - hook文件

import {useState, useEffect} from "react";
import axios from "axios";

// url: 加载什么样的数据
// deps: 什么情况下触发数据的加载
const useURLLoader = (url: string, deps: any[] = []) => {
	const [data, setData] = useState<any>(null);
	const [loading, setLoading] = useState(false);
	// 请求数据
	useEffect(() => {
		setLoading(true); // 设置正在加载
		axios.get(url).then(result => {
			setData(result.data);
		})
	}, deps);
	return [data, loading];
}
export default useURLLoader;

在使用的组件中

import useURLLoader from "./hooks/useURLLoader";
interface IShowResult {
	message: string;
	status: string;
}
const App: React.FC = () => {
	const [data, loading] = useURLLoader("https://baidu.com/xxx", [variable...]);
	const dogResult = data as IShowResult;
	
	return (
		{
			loading ? <p> It's loading the message </p>
					: <img src={dogResult && dogResult.message}/>
		}
	)
}

useRef

useRef值的修改不会影响组件的渲染

useRef包裹数值

const didMountRef = useRef(false);
useEffect(() => {
	if (didMountRef.current) {
	    // 后边渲染的时候输出文字内容
		console.log("this is updated");
	}
	else {
		// 第一次渲染的时候修改值
		didMountRef.current = true;
	}
})

useRef包裹元素

const domRef = useRef<HTMLInputElement>(null);
useEffect(() => {
	if (domRef && domRef.current) {
		domRef.current.focus();
	}
})

<input type="text" ref={domRef}/>

useContext

全局都可以拿到需要的变量,在ThemeContext的包裹下

interface IThemeProps {
	[key: string]: {color: string; background: string;}
}
const themes: IThemeProps = {
	'light': {
		color: "#000000",
		background: "#eeeeee"
	},
	'dark': {
		color: "#ffffff",
		background: "#222222"
	}
};
const ThemeContext = React.createContext(themes.light);
export ThemeContext;

const App: React.FC = () => {
	return (
		<div className="app">
			<ThemeContext.Provider value={themes.light}>
	
			</ThemeContext.Provider>
		</div>
	)
}
// 导入
import {ThemeContext} from ".xxx/App.tsx";
import {useContext} from "react";

const Comp: React.FC = () => {
	// 拿到
	const theme = useContext(ThemeContext);
	const style = {
		color: theme.color,
		background: theme.background
	}
	// 使用
	return (
		<div style={style}>
			<p>Hello World</p>
		</div>
	)
}

hook规则

  • 只在最顶层使用hook,不在循环、条件、嵌套函数中调用hook
  • 只在React函数中调用hook

其他hook

https://usehooks.com/

你可能感兴趣的:(web前端,react.js,前端,typescript)