Icon组件name修改为可选
type Props = {name?: string}const Icon = (props: Props) => {return <svg className="icon">{props.name && <use xlinkHref={'#'+props.name}/>}</svg>}
抽离Input组件
import styled from 'styled-components';import React from 'react';const Label = styled.label`display: flex;align-items: center;> span {margin-right: 16px; white-space: nowrap;}> input {display: block;height: 72px;width: 100%;background: none;border: none;}`;type Props = {label: string;} & React.InputHTMLAttributes<HTMLInputElement> // 继承input的所有属性const Input: React.FC<Props> = (props) => {const {label, children, ...rest} = props;return (<Label><span>{props.label}</span><input {...rest} /></Label>);};export {Input};
使用Input
const NoteSection: React.FC<Props> = (props) => {const note = props.valueconst onChange: ChangeEventHandler<HTMLInputElement> = (e) => {props.onChange(e.target.value);}return (<Wrapper><Input label="备注" type="text" placeholder="在这里输入备注" defaultValue={note} onChange={onChange} /></Wrapper>)}
编辑标签功能
updateTag
const updateTag = (id:number, name: string) => {const tag = {id,name}const newTags = JSON.parse(JSON.stringify(tags))let index = -1for (let i = 0; i<newTags.length; i++){if(newTags[i].id === id) {index = i;break;}}if(index >= 0){newTags.splice(index, 1, tag)}setTags(newTags)}
React不提倡直接修改源数据
setState时要传一个全新的对象才能刷新页面
更优雅的更新和删除tag
const updateTag = (id:number, name: string) => {setTags(tags.map(tag => tag.id === id ? {id, name} : tag))}const deleteTag = (id:number) => {setTags(tags.filter(tag => tag.id !== id))}
useHistory
使用useHistory控制路由的回退,前进,或跳转到指定路径
import {history} from 'react-router-dom'const history = useHistory()history.goBack() // 回退history.push('/') // 跳转到指定路径
使用window.history.back()也一样能实现跳转,相当于点击浏览器的回退按钮
回退时页面会刷新吗?不会
2种方法验证:
- 在控制台查看,当页面刷新时一定会有新的请求
- 在入口文件index.tsx中console.log, 页面刷新必然执行入口文件
让Icon支持onClick
<Icon name="left" onClick={()=> history.goBack()}/>
type Props = {name?: string} & React.SVGAttributes<SVGElement>const Icon = (props: Props) => {const {name, children, ...rest} = propsreturn <svg className="icon" {...rest}>{props.name && <use xlinkHref={'#'+name}/>}</svg>}
注意如果className也在…rest里面,如果从外部传入className, 就会覆盖掉原有的className=”icon”
所有className要提出来
const Icon = (props: Props) => {const {name, children, className, ...rest} = propsreturn <svg className="icon" {...rest}>{props.name && <use xlinkHref={'#'+name}/>}</svg>}
使用classnames库自动合并classname
安装
npm install classnamesnpm install --save-dev @types/classnames
使用
import cs from 'classnames'const Icon = (props: Props) => {const {name, children, className, ...rest} = propsreturn <svg className={cs("icon",className)} {...rest}>{props.name && <use xlinkHref={'#'+name}/>}</svg>}
