React + ts の高度な
状態制約またはクラス コンポーネントの状態の属性制約
:
import React, {
Component } from 'react'
interface IState {
name: string
}
export default class App extends Component<any, IState> {
name!: string
state = {
name: "lihua"
}
render() {
return (
<div>
app-{
this.state.name.substring(0, 1).toUpperCase() + this.state.name.substring(1)}
<button onClick={
() => {
// 这里我们会发现,无论我们给name修改成什么类型的数据,都不会给我们报错,只有我们点击了,在浏览器运行了才知道
// 通过泛型 + interface, 第一个是对属性声明,第二个是状态声明 我们可以清楚的知道哪里报错了
// this.setState({
// name: 1111
// })
this.setState({
name: "xiaoming"
})
}}>点击</button>
</div>
)
}
}
属性
import React, {
Component } from 'react'
export default class App extends Component {
render() {
return (
<div>
<Child name="bbbb"/>
</div>
)
}
}
interface IProps {
name:string
}
class Child extends Component<IProps,any>{
render(){
return <div>
child-{
this.props.name}
</div>
}
}
機能コンポーネント内の状態制約またはプロパティ制約の状態
:
import {
useState} from 'react'
export default function App() {
const [name, setname] = useState<string>("kerwin")
return (
<div>
app-{
name.substring(0,1).toUpperCase()+name.substring(1)}
<button onClick={
()=>{
setname("xiaoming")
}}>click</button>
</div>
)
}
属性:
import React from 'react'
export default function App() {
return (
<div>
app
<Child name="aaa"/>
</div>
)
}
interface IProps {
name:string
}
// function Child(props:IProps){
// return <div>child-{props.name}</div>
// }
const Child:React.FC<IProps> = (props)=>{
return <div>child-{
props.name}</div>
}
ルーター v6 + 反応 v18 + ts + redux :
src/router/index.tsx
import {
RouteObject } from "react-router-dom";
import Cinema from '../views/Cinema'
import Detail from '../views/Detail'
import Film from '../views/Film'
import My from '../views/My'
const routes: RouteObject[] = [
{
path: '/',
element: <Film />
},
{
path: '/cinema',
element: <Cinema />
},
{
path: '/my',
element: <My />
}, {
path: '/detail/:id',
element: <Detail />
}
]
export default routes
ストア/store.ts
import {
createStore } from 'redux'
interface IAction {
type: string,
payload?: any
}
interface IState {
isshow: boolean
}
const reducer = (preState: IState = {
isshow: false
}, action: IAction) => {
const {
type } = action
const newState = {
...preState }
switch (type) {
case "show":
newState.isshow = true
return newState
case "hidden":
newState.isshow = false
return newState
default:
return preState;
}
}
const store = createStore(reducer)
export default store
ビュー/シネマ.tsx:
import React from 'react'
export default function Cinema() {
return (
<div>Cinema</div>
)
}
views/Detail.tsx:
import React, {
useEffect } from 'react'
import {
useDispatch, useSelector } from 'react-redux'
import {
useParams } from 'react-router-dom'
export default function Detail() {
const param = useParams()
const dispath = useDispatch()
const {
isshow } = useSelector((state: any) => ({
isshow: state.isshow }))
useEffect(() => {
console.log(isshow);
dispath({
type: "show" })
console.log(isshow);
return () => {
dispath({
type: "hidden" })
console.log(isshow);
}
// eslint-disable-next-line
}, [])
return (
<div>Detail -{
param.id}
{
isshow && <button>11111</button>}
</div>
)
}
ビュー/Film.tsx:
import React, {
useEffect, useState } from 'react'
import axios from 'axios'
import {
useNavigate } from 'react-router-dom'
interface IItem {
filmId: number,
name: string
}
export default function Film() {
const [list, setlist] = useState([])
const navigate = useNavigate()
useEffect(() => {
axios({
url: "https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=5420934",
headers: {
'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529"}',
'X-Host': 'mall.film-ticket.film.list'
}
}).then((res) => {
setlist(res.data.data.films)
})
}, [])
return (
<div>
<ul>
{
list.map((item: IItem) => {
return (
<li onClick={
() => {
navigate(`/detail/${
item.filmId}`)
}} key={
item.filmId}>{
item.name}</li>
)
})
}
</ul>
</div>
)
}
ビュー/My.tsx:
import React from 'react'
export default function My() {
return (
<div>My</div>
)
}
アプリ.tsx:
import React from 'react';
import {
useRoutes } from 'react-router-dom';
import './App.css';
import routes from './ts-redux/router';
function App() {
const Views = () => useRoutes(routes)
return (
<Views />
);
}
export default App;
インデックス.tsx:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import {
BrowserRouter } from 'react-router-dom';
import {
Provider } from "react-redux";
import store from './ts-redux/store/store';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<Provider store={
store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
ts は実際には非常に理解しやすく、前の基本は完了しており、さらに入力すると慣れてきますし、何度も使用すると慣れます。
後でアサーションを含む別の例を追加します。
import React, {
Component } from 'react'
interface IState {
text: string,
list: string[]
}
export default class App extends Component<any, IState> {
state = {
text: "",
list: []
}
myref = React.createRef<HTMLInputElement>()
render() {
return (
<div>
<input type="text" ref={
this.myref} />
<button onClick={
() => {
// 可选连接符 ?.
// console.log(this.myref.current?.value);
// 断言
console.log((this.myref.current as HTMLInputElement).value);
this.setState({
list: [...this.state.list, (this.myref.current as HTMLInputElement).value]
})
}}>click</button>
{
this.state.list.map((item, index) => <li key={
index}>{
item}</li>)
}
</div>
)
}
}