-
react
组件可以是:class组件
、函数式组件
,然后又细分有状态组件(state)
、无状态组件
,还有其他的类型,不在记录范围内。 -
setState
是在class
组件中使用的,useState
等hooks是在函数式组件中使用的,在react 16.7
开始(具体不明)可以使用,但是官方建议react 16.8
正式使用; -
组件销毁跟
vue
类似,在父组件可以用一个变量show{show && <Component>}
,show为false则会销毁(或者不渲染)
setState
setState
是异步的,不会立即生效;如果依赖这次操作,可以用另一种写法:setState({prop}, callback)
setState集中处理
函数声明
// change事件
handlerChange = (searchKey, value) => {
const search = Object.assign({}, this.state.searchData);
if (searchKey === 'transactionTime') {
// 交易日期
search.transactionTimeStart = value.length
? moment(value[0]).format('YYYY-MM-DD')
: '';
search.transactionTimeEnd = value.length
? moment(value[1]).format('YYYY-MM-DD')
: '';
}else {
search[searchKey] = value;
}
this.setState({
searchData: search
});
};
复制代码
jsx
<Input
style={{ width: 120 }}
placeholder="请输入"
onChange={e => this.handlerChange('coin', e.target.value)}
/>
复制代码
useState
hooks在react函数式组件中使用,
- useState用来代替class组件中state声明、setState更新数据;
- useEffect,会在组件初始化、数据更新时被调用,也就是可以用来代替
componentDidMount
/componentDidUpdate
,看到其他掘友的文章说componentWillUnmount时会调用这个函数return 出来的函数,具体实践后就清楚了
useState使用
以下代码可以在codesandbox.io中运行
import ReactDOM from "react-dom";
import React, { useState } from "react";
function NameComp() {
// 可以传入“initName”作为初始化数据
const [name, setName] = useState("initName");
const nameChange = e => setName(e.target.value);
return (
<div>
<p>{name}</p>
<input onChange={nameChange} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<NameComp />, rootElement);
复制代码
useEffect/useLayoutEffect
useEffect
浏览器完成画面渲染之后才会延迟调用 useEffect,因此会使得额外操作很方便。
可以存在多个,第二个参数可选
- 有第二个参数(依赖)的话,会根据依赖变化才执行
- 第二个参数不传的话,每次update都会调用;
- 第二个参数为空数组的话,相当于 componentDidMount;
- 如果 return 一个函数,这个函数会在相当于 componentWillUnmount 的时候执行
const [offsetW, setOffsetW] = useState(0);
const [offsetH, setOffsetH] = useState(0);
const [pngUrl, setPngUrl] = useState('');
const [mdUrl, setMdUrl] = useState('');
const [exportName, setExportName] = useState('');
let preview, maxCodeWidth;
useEffect(() => {
// 显示的内容
preview = document.querySelector('[class^=md-content]');
// 获取 code 部分的最大宽度,防止导出图片时,横向滚动条的部分截断
let codeContent = preview.querySelectorAll('pre>code');
let codeWidth = Array.from(codeContent).map(codeTag => codeTag.offsetWidth);
maxCodeWidth = Math.max(...codeWidth);
setOffsetW(maxCodeWidth);
setOffsetH(preview.offsetHeight);
exportfn('png');
exportfn('md');
// 回调的函数会在 unmount 时执行
return () => console.log('Export unmount');
// 传入第二个参数, 空数组,表示update不执行,[offsetW]表示 offsetW 更新时执行
}, []);
复制代码
useEffect(() => {
console.log('detail mount: ', process.env.NODE_ENV);
return () => {
console.log('detail unmount');
}
}, []);
复制代码
useLayoutEffect
与useEffect没有太大区别,详看文档
useCallback/useMemo
useCallback
依赖项不变或第二个参数传入空值的话,会执行,但是return的东西不会更新;
类似于 vue 中的 watch,需要先手动调用一次
// pages/detail.js
// ...
const [count, setCount] = useState(0);
const [num, setNum] = useState(0);
// 依赖项 num 不变化的话 会执行,但是不会 return 一个新的 count,即使 count 变化了
const memorized1 = useCallback(() => {
console.log(count);
return count;
}, [num])();
// ...
复制代码
useMemo
依赖项不变或第二个参数传入空值的话,不执行;
渲染期间根据依赖项执行,不传入依赖的话,每次state更新都会执行,不需要手动调用一次
// pages/detail.js
// ...
const [count, setCount] = useState(0);
const [num, setNum] = useState(0);
// 依赖项 num 不变化的话 不执行
const memorized2 = useMemo(() => {
console.log(count);
return count;
}, [num]);
// ...
复制代码
useRef
元素本身:useRef返回值.current
function Comp1() {
const inputEl = useRef(null);
function Clk() {
inputEl.current.focus();
}
return (
<>
<button onClick={Clk}>count+</button>
<input ref={inputEl} type="text" />
</>
);
}
复制代码
useReducer/useContext
具体看这里:React状态管理:redux,rematch,useReducer
useImperativeHandle
以下来自官网文档
useImperativeHandle(ref, createHandle, [deps])
复制代码
useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle 应当与 forwardRef 一起使用:
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
复制代码
在本例中,渲染 的父组件可以调用 fancyInputRef.current.focus()。
useDebugValue
useDebugValue 可用于在 React 开发者工具中显示自定义 hook 的标签。
useDebugValue(value)
复制代码
自定义Hooks
封装一些Hooks的方法,暴露出接口,参考这里
function Comp2() {
function useNumCalc(num) {
let [count, setCount] = useState(num);
return [count, () => setCount(count + 1), () => setCount(count - 1)];
}
const [num, numPlus, numMinus] = useNumCalc(1);
return (
<>
num: {num}
<button onClick={numPlus}>numPlus</button>
<button onClick={numMinus}>numMinus</button>
</>
);
}
复制代码
数据展示
可以用一个字段决定组件是否渲染,如show && <Component />
,show为true
时渲染; 注意如果show是数组,应该用show.length > 1
作为条件,而不是show.length && <Component />
表格列自定义内容render
: (antd)
...
<LocaleProvider locale={zh_CN}>
<Table
bordered
loading={this.state.tableLoading}
dataSource={this.state.tableData}
pagination={this.getPaginationProps()}
>
{Object.keys(columnText).map(key =>
key === 'operation' ? ( // 操作列
<Column
title={columnText[key]}
align="center"
dataIndex={key}
key={key}
render={(text, row) => (
<div>
<span className={styles.a} onClick={() => this.edit(row)}>
修改
</span>
 
<span
className={styles.a}
onClick={() => this.delete(row)}
>
删除
</span>
</div>
)}
/>
) : (
// 其他列
<Column
title={columnText[key]}
align="center"
dataIndex={key}
key={key}
/>
)
)}
</Table>
</LocaleProvider>
...
复制代码
表格列抽出遍历:(antd)
// 省略其他代码
...
render() {
const { Column } = Table;
// 表格列 对应的 key和名称
const columnText = {
No: '序号',
coinName: '币种',
maxAmountPerOrder: '单笔限额',
maxAmountPerDay: '日累计限额',
latestUpdatedTime: '最后编辑时间',
latestEditor: '最后编辑人',
operation: '操作'
};
return (
<div className={styles.withdrawalConfig}>
<LocaleProvider locale={zh_CN}>
<Table
bordered
scroll={{ y: this.state.tableHeight }}
dataSource={tableData}
pagination={this.getPaginationProps()}
>
{Object.keys(columnText).map(key =>
key === 'operation' ? ( // 操作列
<Column
title={columnText[key]}
align="center"
dataIndex={key}
key={key}
width="12%"
render={(text, row) => (
<div>
<span className={styles.a} onClick={() => this.edit(row)}>
修改
</span>
 
<span
className={styles.a}
onClick={() => this.delete(row)}
>
删除
</span>
</div>
)}
/>
) : (
// 其他列
<Column
title={columnText[key]}
align="center"
dataIndex={key}
key={key}
width={key === 'No' ? '6%' : '12%'}
/>
)
)}
</Table>
</LocaleProvider>
</div>
);
}
...
复制代码
所有评论(0)