JavaScript的问题之一是其动态类型化的性质,这意味着直到运行时才知道数据和变量类型。这可能有很多副作用。例如,由于变量可以是任何事实,这可能导致代码库混乱。
为了解决此问题,Microsoft发布了TypeScript。TypeScript的首席架构师Anders Hejlsberg说:“What if we could strengthen JavaScript with the things that are missing for large scale application development, like static typing, classes [and] modules…? That’s what TypeScript is about.”//“如果我们可以利用大规模应用程序开发所缺少的东西(如静态类型,类[和]模块……)来增强JavaScript,该怎么办?这就是TypeScript的目的。”
TypeScript立即成为使用最广泛的JavaScript静态类型版本。它使JavaScript开发人员能够静态键入数据和变量。很快,它就被引入React.js中,从而使React开发人员可以使用TypeScript编写其React应用。
但这是有代价的:TypeScript类型和语法可能难以跟上,尤其是与React一起使用时。
React具有许多功能,例如props, class components, function components, function params, components lifecycle hooks, and member properties。由于在TypeScript中键入这些内容并不容易,因此本文旨在为初学者和高级React开发人员提供快速参考和学习指南。
通过这,您将能够在React中快速查找最佳实践和通用TS类型。准备?让我们开始吧。
TypeScript类型
TypeScript有一个typings文件夹,用于保存扩展名为* .d.ts的文件。这些文件包括推断值将采用何种形状的接口。这就是使TypeScript能够将数据类型引入JavaScript的原因。
接口描述了值的形式:
type AppState {
propOne: number;
propTwo: string
}
AppState描述其数据类型的值将是什么样。首先,我们推断它将是一个包含属性propOne和propTwo的对象,propTwo前者是数字类型,后者是字符串类型。分配一个布尔类型的propOne将导致TypeScript抛出TypeError。
当我们在React项目中包含TypeScript时,每个React元素都有一个定义其形状的接口。让我们从函数组件开始。
函数组件
函数组件是正常的函数,它们在React中返回JSX元素,并用于创建视图。最初,它们是无状态的组件,但是随着React钩子(React hooks)的到来,它们可以变成有状态的和智能的
定义React函数组件的React.FunctionComponent形状如下:
function App: React.FunctionComponent<> {
return (
<>
// ...
</>
)
}
我们也可以使用速记 React.FC:
function App: React.FC<> {
return (
<>
// ...
</>
)
}
React.FunctionComponent或React.FC明确描述函数组件的返回类型。
我们可以在箭头中输入props定义<>。
type AppProps = {
message: string;
age: number;
};
AppProps是传递给App的props将采用的接口,因此如果它可以接收props,我们可以在下面编写App组件:
type AppProps {
message: string;
age: number;
}
function App: React.FC<AppProps>(props: AppProps) {
return (
<>
// ...
</>
)
}
我们可以使用?在键入中设置可选值:
type AppProps {
message: string;
age?: number;
}
现在,age属性变为可选。该App组件可以呈现,省略其props对象的年龄属性。
我们可以在箭头内省略类型声明<>。
function App<{message: string; age: number;}>({message: string; age: number;}: AppProps) {
// ...
}
可以嵌入函数组件中的内部函数,如下所示:
function App<{message: string; age: number;}>({message: string; age: number;}: AppProps) {
// ...
function clickHandler (val: number) {
// ...
}
return (
<>
<button onClick={() => clickHandler(45)}
</>
)
}
类组件
类组件用于在React中创建视图。它们本质上是构建块。一个React应用程序可以包含许多应用程序,它们定义了一小部分UI应该如何显示。
类组件具有生命周期挂钩,我们可以将其挂钩以在组件生命周期的任何状态下运行自定义代码。
他们使用React.Component<>:
class App extends React.Component<> {
// ...
}
Props 和 State
您可以为类组件提供Props和State状态类型参数:
type AppProps = {
message: string;
age: number;
};
type AppState = {
id: number;
};
class App extends React.Component<AppProps, AppState> {
state: AppState = {
id: 0
};
// ...
}
props类型AppProps插入在状态类型AppState之前的<>箭头之间。
类方法
如果您有用于类方法的参数,则可以键入参数:
class App extends React.Component<AppProps, AppState> {
state: AppState = {
id: 0
};
clickHandler = (val: number) => {
// ...
}
render() {
return (
<>
<button onClick={() => this.clickHandler(90)}>Click</button>
</>
)
}
}
函数组件和defaultProps类型
defaultProps用于定义传递给React组件的props参数的默认值。defaultProps当在运行时丢失了可能可用的props时,有助于防止错误。其中的值defaultValues立即成为props的值。
React.FC包含defaultProps在函数组件中时会被丢弃,因为类型推断中的某些边缘情况在TypeScript中仍然是一个问题。
这意味着props的使用与通常一样:
type AppProps = { message: string; age: number } & typeof defaultProps;
const defaultProps = {
message: "",
age: 0
};
function App(props: AppProps) {
// ...
};
App.defaultProps = defaultProps;
表单和事件
表单通常用于收集内部状态的信息。它们主要用于登录和注册页面,因此提交的信息可以通过表单收集并发送到服务器进行处理。
React.FormEvent 通常用于键入元素中的事件。
class App extends React.Component<> {
clickHandler = (e: React.FormEvent<HTMLButtonElement>) => {
// ...
}
changeHandler = (e: React.FormEvent<HTMLInputElement>) => {
// ...
}
render() {
return (
<div>
<button onClick={this.clickHandler}>Click</button>
<input type="text" onChange={this.changeHandler} />
</div>
)
}
}
clickHandler和changeHandler参数e均具有React.FormEvent类型。
我们可以省略使用React.FormEvent输入处理程序的参数,而改为输入处理程序的返回值。 这是使用React.ChangeEventHandler完成的:
class App extends React.Component<> {
clickHandler: React.FormEvent<HTMLButtonElement> = (e) => {
// ...
}
changeHandler: React.FormEvent<HTMLInputElement> = (e) => {
// ...
}
render() {
return (
<div>
<button onClick={this.clickHandler}>Click</button>
<input type="text" onChange={this.changeHandler} />
</div>
)
}
}
React.ChangeEvent 是可用于输入事件处理程序参数的事件类型:
class App extends React.Component<> {
clickHandler = (e: React.ChangeEvent<HTMLButtonElement>) => {
// ...
}
changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
// ...
}
render() {
return (
<div>
<button onClick={this.clickHandler}>Click</button>
<input type="text" onChange={this.changeHandler} />
</div>
)
}
}
注意,T是注册事件的元素的类型。
Button
这描述了button元素的React.ChangeEvent类型。按钮是HTMLButtonElement类的实例。在这里,T将是HTMLButtonElement,而React.ChangeEvent将是React.ChangeEvent。
Inputs
这描述了React.ChangeEvent所有输入元素:“text,” “password,” “color,” “button,” “media,”等。它们都是HTMLInputElement类的实例。对于所有types= [“text”, “password”, etc]
T将是HTMLTnputElement。React.ChangeEvent将是React.ChangeEvent。
TextArea
这是指文本区域元素的React.ChangeEvent,并且文本区域元素是HTMLTextAreaElement的实例。
T将是HTMLTextAreaElement。 React.ChangeEvent将是React.ChangeEvent。
Select
Select元素用于创建带有选择选项的下拉列表。选择元素是HTMLSelectElement的实例。
T将是HTMLSelectElement。React.ChangeEvent将是React.ChangeEvent。
Form
表单元素从DOM收集信息。表单元素是HTMLFormElement的实例。T将是HTMLFormElement。React.ChangeEvent将是React.ChangeEvent。
Video, Audio
视频用于在浏览器上播放视频。video元素是HTMLVideoElement的实例。这描述了如何在Form元素中设置React.ChangeEvent。
T将是HTMLVideoElement。 React.ChangeEvent将是React.ChangeEvent。
依次,音频用于在浏览器中播放音频文件(mp3,aac等)。音频元素是HTMLAudioElement的实例。
T将是HTMLAudioElement。 React.ChangeEvent将是React.ChangeEvent。
React.SyntheticEvent
当您不关心事件的类型时,可以使用以下类型:
class App extends React.Component<> {
submitHandler = (e: React.SyntheticEvent) => {
// ...
}
render() {
return (
<form onSubmit={this.submitHandler}>
...
</form>
)
}
}
Hooks
Reactv16.8 +支持Hooks。它们允许我们在函数组件中使用状态。
useState
这用于设置函数组件中的状态,并且该状态在组件的整个生命周期中都保持活动状态。
const [state, setState] = useState(0)
我们可以推断state为数字,而setState为推断数字的函数。
const [state, setState] = useState<number, (v: boolean) => : void >(0)
如果state带一个对象:
type StateObject = {
loading: boolean
}
const [state, setState] = useState<StateObject, (boolean) => : void >({loading: true})
通常,useState初始值为null。我们可以使用联合类型来显式声明类型,如下所示:
const [state, setState] = useState<StateObject | null, (boolean) => : void >(null)
这个StateObject | null告诉TypeScript状态可以是StateObject类型或null类型。
useReducer
useReducer允许我们维护状态并同时从我们的函数组件向store分发操作。它具有一个初始状态和一个reducer函数:
const intialState = {
loggedIn: false
}
function reducer(state, action) {
// ...
}
const [state, dispatch ] = useReducer(initialState, reducer)
我们可以定义state的类型,然后根据返回类型键入reducer函数。可以根据reducer函数上的action参数类型来输入调度:
type LogginState = {
loggedIn: boolean;
};
type ActionType = {
type: string;
payload: boolean;
};
const intialState: LogginState = {
loggedIn: false
}
function reducer(state: LogginState, action: ActionType): LogginState {
// ...
}
const [state, dispatch ] = useReducer<LogginState, (v: ActionType) => : void>(initialState, reducer)
useRef
useRef允许我们访问React节点中的ref,并在组件的整个生命周期内对其进行维护。
null类型主要传递给useRef,因此键入看起来像这样:
const ref= useRef<HTMLElement | null>(null)
我们可以更具体地说明我们要引用的元素类型:
// this types useRef to button elements
const buttonRef= useRef<HTMLButtonElement | null>(null)
// this types useRef to input elements
const inputRef= useRef<HTMLInputElement | null>(null)
另外,useRef可用于React.Component:
const inputRef= useRef<React.Component | null>(null)
useContext
useContext允许我们在函数组件的整个生命周期中创建和维护上下文。使用React Context API创建上下文。
以下是使用useContext和createContext创建上下文的方法:
const authContext = createContext({isAuth: true})
const context = useContext(authContext)
的默认值类型createContext将构成其参数类型的基础:
type AuthType = {
isAuth: boolean;
};
const authContext = createContext<AuthType>({isAuth: true})
此外,useContext参数类型将为AuthType:
const context = useContext<AuthType>(authContext)
最后
希望您发现本指南对您有帮助。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!