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.value
const 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 = -1
for (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} = props
return <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} = props
return <svg className="icon" {...rest}>
{props.name && <use xlinkHref={'#'+name}/>}
</svg>
}
使用classnames库自动合并classname
安装
npm install classnames
npm install --save-dev @types/classnames
使用
import cs from 'classnames'
const Icon = (props: Props) => {
const {name, children, className, ...rest} = props
return <svg className={cs("icon",className)} {...rest}>
{props.name && <use xlinkHref={'#'+name}/>}
</svg>
}