React与TS配合
props限制
npx create-react-app react-ts-study --template typescript
src/index.tsx
import App from './01_react-ts-props';
src/01_react-ts-props.tsx
import React from 'react'
interface WelcomeProps {
msg?: string //可选
count: number
list: string[]
info: { username: string; age: number }
state?: 'loading' | 'success' | 'error'
}
const Welcome = (props: WelcomeProps) => {
//设置默认值
const { count = 0 } = props
return <div>Welcome,{count}</div>
}
// const Welcome: React.FC<WelcomeProps> = (props) => {
//设置默认值
// const { count = 0 } = props
// return <div>Welcome,{count}</div>
// }
export default function App() {
return (
<div>
<Welcome
msg="hello"
count={123}
info={{ username: 'alex', age: 20 }}
list={['1', '2']}
state={'loading'}></Welcome>
</div>
)
}
children与event的限制
import React from 'react'
interface WelcomeProps {
children?: React.ReactNode
handleMsg?: (ev: React.MouseEvent<HTMLButtonElement>) => void
}
const Welcome = (props: WelcomeProps) => {
const handChange = (ev: React.ChangeEvent<HTMLInputElement>) => {}
return (
<div>
Welcome
<button onClick={props.handleMsg}>点击</button>
<input type="text" onChange={handChange} />
</div>
)
}
export default function App() {
return (
<div>
<Welcome handleMsg={(ev) => {}}>
<div>div</div>
123
</Welcome>
</div>
)
}
style与component
import React from 'react'
interface WelcomeProps {
style: React.CSSProperties
component: React.ComponentType<HeaderPros>
}
interface HeaderPros {
username: string
}
const Welcome = (props: WelcomeProps) => {
return (
<div>
Welcome
<props.component username="alex"></props.component>
</div>
)
}
function Header(props: HeaderPros) {
return <div>hello Header</div>
}
export default function App() {
return (
<div>
<Welcome component={Header} style={{ border: '1px red solid' }}></Welcome>
</div>
)
}
use函数限制
import React, { useEffect, useRef, useState } from 'react'
interface WelcomeProps {}
const Welcome = (props: WelcomeProps) => {
return <div>Welcome</div>
}
export default function App() {
// const [count, setCount] = useState(0)
const [count, setCount] = useState<string | number>(0)
const [list, setList] = useState<string[]>([])
const [info, setInfo] = useState<{ username: string; age: number } | null>(
null
)
const myRef = useRef<HTMLButtonElement>(null)
useEffect(() => {
console.log(myRef.current?.innerHTML)
return () => {}
}, [])
const handleClick = () => {
setCount('1')
setList(['123'])
setInfo({ username: 'alex', age: 23 })
}
return (
<div>
<button onClick={handleClick}></button>
<Welcome></Welcome>
{count},{list}
</div>
)
}
对路由的限制
npm i react-router-dom
src/index.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
// import App from './App'
import reportWebVitals from './reportWebVitals'
import { RouterProvider } from 'react-router-dom'
import router from './router'
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(
<React.StrictMode>
<RouterProvider router={router}></RouterProvider>
</React.StrictMode>
)
reportWebVitals()
src/router/index.ts
import { createBrowserRouter } from 'react-router-dom'
import Index from '../views/Index/Index'
import Login from '../views/Login/Login'
import User from '../views/User/User'
import App from '../App'
import React from 'react'
import type { RouteObject } from 'react-router-dom'
declare module 'react-router' {
interface NonIndexRouteObject {
meta?: { title: string }
}
interface IndexRouteObject {
meta?: { title: string }
}
}
export const routes: RouteObject[] = [
{
path: '/',
element: React.createElement(App),
meta: { title: '/' },
children: [
{
path: 'index',
element: React.createElement(Index),
meta: { title: 'index' },
},
{
path: 'user',
element: React.createElement(User),
},
{
path: 'login',
element: React.createElement(Login),
},
],
},
]
const router = createBrowserRouter(routes)
export default router
src/App.tsx
import { Outlet } from 'react-router-dom'
function App() {
return (
<div className="App">
<Outlet></Outlet>
</div>
)
}
export default App
RTK
npm i @reduxjs/toolkit
npm i react-redux
src/index.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
// import App from './App'
import reportWebVitals from './reportWebVitals'
import { RouterProvider } from 'react-router-dom'
import router from './router'
import { Provider } from 'react-redux'
import store from './store'
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(
<React.StrictMode>
<Provider store={store}>
<RouterProvider router={router}></RouterProvider>
</Provider>
</React.StrictMode>
)
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()
src/store/modules/user.ts
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
export const loginAction = createAsyncThunk(
'users/loginAction',
async (userId: number) => {
const response = await new Promise((resolve) => {
resolve('response data')
})
return response
}
)
const userSlice = createSlice({
name: 'user',
initialState: {
name: 'alex',
},
reducers: {
//限定payload类型
change(state, action: PayloadAction<string>) {
state.name = action.payload
},
},
})
//限定payload类型
export const { change } = userSlice.actions
export default userSlice.reducer
src/store/index.ts
import { useDispatch } from 'react-redux'
import { configureStore } from '@reduxjs/toolkit'
import userReducer from './modules/user'
const store = configureStore({
reducer: {
user: userReducer,
},
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
export const useAppDispatch: () => AppDispatch = useDispatch
export default store
src/views/Index/Index.tsx
import React, { useState } from 'react'
import { useSelector } from 'react-redux'
import { RootState, useAppDispatch } from '../../store'
import { change, loginAction } from '../../store/modules/user'
import { Button, Rate } from 'antd'
export default function Index() {
const name = useSelector((state: RootState) => state.user.name)
const dispatch = useAppDispatch()
const handleClick = () => {
// dispatch({
// type: 'user/change',
// payload:'yuan'
// })//这种写法没法限制payload类型
dispatch(change('yuan')) //限定payload类型
dispatch(loginAction(123))
}
const [rate, setRate] = useState(3)
return (
<div>
<Button type="primary" onClick={handleClick}>
点击
</Button>
Index,{name}
<Rate value={rate} onChange={setRate}></Rate>
</div>
)
}
antd
npm i antd
src/views/Index/Index.tsx
import React, { useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import type { RootState } from '../../store'
import { change } from '../../store/modules/user'
import { Button, Rate } from 'antd'
export default function Index() {
const name = useSelector((state: RootState) => state.user.name)
const dispatch = useDispatch()
const handleClick = () => {
// dispatch({
// type: 'user/change',
// payload:'yuan'
// })//这种写法没法限制payload类型
dispatch(change('yuan')) //限定payload类型
}
const [rate, setRate] = useState(3)
return (
<div>
<Button type="primary" onClick={handleClick}>
点击
</Button>
Index,{name}
<Rate value={rate} onChange={setRate}></Rate>
</div>
)
}
![image-20230118000332216](https://imguploadweiqi.oss-cn-guangzhou.aliyuncs.com/image-20230118000332216.png)