- React 最差实践
- 1、逻辑内嵌(Using Logic Inside Render)
- 2、用匿名函数污染render方法(Polluting Render method using anonymous functions)
- 3、用&& 来有条件的渲染组件 (Using && to conditionally Render Component)
- 4、三元嵌套(Nesting Ternary in Render)
- 5、不排序的props( Not Sorting Props)
- 6、不解构props和state(Not destructuing props and state)
- 7、不使用useCallback,useMemo和React.memo(Not using useCallback, useMemo hooks and React.memo)
- 8、不清理事件监听和定时器(Not Cleaning event listeners and timers)
- 9、一对一的透传props(Passing props one by one)
- 10、使用index做为key(Using Index as a key)
- 11、不使用 React Dev Tools (Avoiding React Dev Tools)
- 12、使用内置 CSS(Using inline CSS)
- 13、रायताफैलाना
- 14、到处是div(divs everywhere )
- 15、使用div作为button ( div as button)
React 最差实践
Hello word 🌏
就像一个木匠总是在在耳朵上夹着一根铅笔,任何时间需要它的时候就会以闪电般的速度把它拿出来,同样的,我相信这些实践应该时刻记在心里无论什么时间你写React app的的时候。我们应该认真注意这些不仅仅能提供更好的性能,还能为终端用户提供更流畅的体验和提高代码的可维护性。
1、逻辑内嵌(Using Logic Inside Render)
这在类组件中是比较常见的,但是随着函数组件的出现降低了类组件的使用,但是仍然会犯这样的错误。
//Badconst Product = () => {return (<div className={addToChart ? 'active' : 'inactive'}><div>{isLogin ? 'Login' : 'Checkout'}</div></div>)}
//Goodconst Product = () => {const className = addToChart ? 'active' : 'inactive';const text = isLogin ? 'Login' : 'Checkout';return (<div className={}><div>{text}</div></div>)}
2、用匿名函数污染render方法(Polluting Render method using anonymous functions)
不要用匿名函数在render和return方法里。这回降低可读性,增加代码复杂度,也会影响性能。
// Badconst Product = () => {return (<button onClick={() => {updateProduct();showPayment();}}>buy</button>)}
// Goodconst Product = () => {const handleBuy = () => {updateProduct();showPayment();}return (<button onClick={handleBuy}> buy </button>)}
3、用&& 来有条件的渲染组件 (Using && to conditionally Render Component)
考虑下面的代码
//const Product = () => {const showTitle = 0;return <div> { showTitle && <h1>Mac</h1>}</div>}
这会渲染出什么?
这会渲染出0,尽管0 是一个假值,但是0 同样是一个number,而react是会渲染number的。
要解决这个问题或者用 !!将0转换成bool 值,或者用三元运算符。
// 用!!来转换const Product = () => {const showTitle = 0;return <div> { !!showTitle ? <h1>Mac</h1>}</div>}//用三元运算符const Product = () => {const showTitle = 0;return <div> { showTitle ? <h1>Mac</h1> : null}</div>}
4、三元嵌套(Nesting Ternary in Render)
三元嵌套是不被推荐的。很多情况下还是还是不会有这种用法。
// Badconst Product = () => {return <div> { showTitle ? <h1>Mac</h1> : showData ? <Data /> : <ShowData />}</div>}
// goodconst Product = () => {const getJsx = () => {if(showTitle) {return <h1>Mac</h1>} else if (showData) {return <Data />} else {return <NoData />}}return <div> {getJsx()}</div>}
5、不排序的props( Not Sorting Props)
当我们的应用增长时,props的数量,函数参数的数量也会增长。如果我们不对他们进行有效的管理,情况会变的越来越糟糕。建议对props保持有序。这会提高可读性减少debug的时间。
可用这个插件对props进行排序
// Bad<Productprice ={price}isGuest={isGuest}product={product}addToChart={addToChart}query={query}/>const Product = ({ price, addToChart, query, isGuest ) => {return <div></div>}
// Good<ProductaddToChart={addToChart}price ={price}isGuest={isGuest}product={product}query={query}/>const Product = ({addToChart, price, isGuest, query) => {return <div></div>}
6、不解构props和state(Not destructuing props and state)
很多时候,直接用props取值的方式可能或节省一些时间,但随着代码变的庞大会变的很难发现props应用的地方。所以推荐的方式就是总是解构props,state,对象和数组。
// Badconst Product = (props) => {const fetchData = () => {getDefaultNormalizer(props.id, props.user);}return <div><div>{props.title}</div></div>}
// Goodconst Product = (props) => {const {id="", user={}, title ="" } = props;const fetchData = () => {getDefaultNormalizer(id, user);}return <div><div>{title}</div></div>}
7、不使用useCallback,useMemo和React.memo(Not using useCallback, useMemo hooks and React.memo)
8、不清理事件监听和定时器(Not Cleaning event listeners and timers)
不清理计时器和监听器会引起两个问题
1、内存溢出
2、应用中不可预料的状态(同一个计时器的多个实例和事件可能会被注册)
// Badconst Product =() => {const onDcumentClick =() => {};React.useEffect(() => {document.addEventListener('click', onDcumentClick);setTimeOut(() => {}, 5000)}, []);return <div>Product</div>}// GoodReact.useEffect(() => {document.addEventListener('click', onDcumentClick);const timer = setTimeOut(() => {}, 5000)return () => {document.removeEventListener('click', onDcumentClick);clearTimeOut(timer);}}, []);
9、一对一的透传props(Passing props one by one)
// Badconst Product =(props) => {const { title } = props;return (<div><h1>{title}</h1><WatchaddToChart = {props.addToChart}data = {props.data}isGuest = {props.isGuest}/></div>)}// Goodconst Product =(props) => {const { title, ...restProps } = props;return (<div><h1>{title}</h1><Watch {...restProps} /></div>)}
10、使用index做为key(Using Index as a key)
使用index作为key适用于下面两种场景
1、列表是静态的,不会改变。
2、不需要重新渲染,没有添加删除等。
11、不使用 React Dev Tools (Avoiding React Dev Tools)
建议安装 React Dev Tools插件。
1、通过打开这个选项,你可以以可视化的方式检查更新,并能避免一些不必要的渲染。
2、通过使用RDT你可以检查
1、都有哪些props传递给了组件
2、有哪些state是被使用的
3、哪个组件负责渲染特定的组件
4、还有更多…
RDT下载链接
12、使用内置 CSS(Using inline CSS)
在React中不要使用内置CSS。
1、这会有性能问题
2、这会影响代码的可读性和变得更复杂。
有很多方式可以添加样式。
1、使用单独的SCSS或者LESS文件
2、使用styled-component
3、CSS-in-JS
13、रायताफैलाना
看下面的代码
import {getFormateDate} from 'utils';import React from 'react';import Card from './card';const MAX_DELAY = 1000;import get from 'lodash';import {configure} from '@testing-library/react';import {useDispatch} from 'react-redux';const Product React.memo(({ isAdded, title}) => {const className = ptops.isAdded ? 'active': '';configure();const title = `${props.title} Bye || `;React.useEffect(() => {fetchData();},[])const dispath = useDispatch();return (<div><h1 className={className}> {title} </h1></div>)})
上面的代码存在几个问题:
1、没有遵循一定的import顺序
2、在任何地方都创建了变量;
3、在任意的地方初始化hooks;
4、Writing useEffect hools in b.w. code.
当应用变的庞大,维护这样的代码会非常的困难。我们应该遵循一些规则。
导入顺序
- 第三方库
- 自定义组件
- utils方法
- constants常量
- 图片导入
- 为文件创建的特定的constant
(用空行分割每一个导入)
组件规则
- 解构props(如果有的话)
- 解构redux state (如果有的话)
- 初始化state 变量()
- 创建 refs
- 初始化hooks(useDispatch)
- 写完所有的Effects
- 为组件创建特定的const/var/let变量
- 调用函数(如果有的话)
(每部分用空行作为分割)
import React from 'react';import { useDispatch } from 'react-redux';import { configure } from '@testing-library/react';import get from 'lodash';import Card from './card';import { getFormateDate } from 'utils';const MAX_DELAY = 1000;const Product React.memo(({ isAdded, title}) => {const { isAdded, title } = props;const dispath = useDispatch();React.useEffect(() => {fetchData();},[]);const className = isAdded ? 'active': '';const title = `${title} Bye || `;configure();return (<div><h1 className={className}> {title} </h1></div>)})
14、到处是div(divs everywhere )
很多时候我们会忘记语义化,页面导出是DIV。
还是要遵循语义化。
不要忘记 section,article,footer
15、使用div作为button ( div as button)
如果你想吧一个div变成可点击的,不要忘记添加role = 'button'。因为button标签有一些好处
1、可以使用tab进行导航
2、可聚焦 + 可点击
// no role<div onClick={handleClick}><h1 className={className}> {titleShow} </h1></div>
// with role<div onClick={handleClick} role="button"><h1 className={className}> {titleShow} </h1></div>
role的使用不仅仅可以适用于div ,也可以适用于任何的html元素,任何添加了click的元素都应该有role。
