hooks写React组件要注意哪些细节

其他教程   发布日期:2023年08月23日   浏览次数:374

今天小编给大家分享一下hooks写React组件要注意哪些细节的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

01.不需要render的场景下使用useState

在函数组件中我们可以使用

  1. useState
来管理状态,这使得对状态的管理变得很简单,但是也容易被滥用,我们通过下面的代码样例看下容易忽略的地方。

不推荐×

  1. function ClickButton(props){
  2. const [count, setCount] = useState(0)
  3. const onClickCount = () => {
  4. setCount((c) => c + 1)
  5. }
  6. const onClickRequest = () => {
  7. apiCall(count)
  8. }
  9. return (
  10. <div>
  11. <button onClick={onClickCount}>Click</button>
  12. <button onClick={onClickRequest}>Submit</button>
  13. </div>
  14. )
  15. }

问题所在:仔细看上面的代码,乍一看其实也没什么问题,点击按钮更新

  1. count
。但是问题也就出在这里,我们的
  1. return
部分并没有用到 count 状态,而每次
  1. setCount
都会使组件重新渲染一次,而这个渲染并不是我们需要的,多出来的渲染会使得页面的性能变差,因此我们可以改造一下代码,如下代码:

推荐&radic;如果我们只是单纯的想要一个能在组件声明周期内保存的变量,但是变量的更新不需要组件的重新渲染,我们可以使用

  1. useRef
钩子。
  1. function ClickButton(props){
  2. const count = useRef(0)
  3. const onClickCount = () => {
  4. count.current++
  5. }
  6. const onClickRequest = () => {
  7. apiCall(count.current)
  8. }
  9. return (
  10. <div>
  11. <button onClick={onClickCount}>Click</button>
  12. <button onClick={onClickRequest}>Submit</button>
  13. </div>
  14. )
  15. }

02.使用了router.push而非link

在React SPA应用中,我们用react-router来处理路由的跳转,我们很经常在组件中写了一个按钮,通过点击按钮的事件来处理路由的跳转,如下代码:

不推荐&times;

  1. function ClickButton(props){
  2. const history = useHistory()
  3. const onClickGo = () => {
  4. history.push('/where-page')
  5. }
  6. return <button onClick={onClickGo}>Go to where</button>
  7. }

问题所在:尽管上述代码可以正常工作,但是却不符合Accessibility(易访问性设计)的要求,此类按钮并不会被屏幕阅读器当作一个可以跳转的链接。因此我们可以改造一下代码,如下代码:

推荐&radic;

  1. function ClickButton(props){
  2. return <Link to="/next-page">
  3. <span>Go to where</span>
  4. </Link>
  5. }

03.通过useEffect来处理actions

有时候,我们只想在 React 更新 DOM 之后运行一些额外的代码。比如发送网络请求,手动变更 DOM,记录日志。

不推荐&times;

  1. function DataList({ onSuccess }) {
  2. const [loading, setLoading] = useState(false);
  3. const [error, setError] = useState(null);
  4. const [data, setData] = useState(null);
  5. const fetchData = () => {
  6. setLoading(true);
  7. callApi()
  8. .then((res) => setData(res))
  9. .catch((err) => setError(err))
  10. .finally(() => setLoading(false));
  11. };
  12. useEffect(() => {
  13. fetchData();
  14. }, []);
  15. useEffect(() => {
  16. if (!loading && !error && data) {
  17. onSuccess();
  18. }
  19. }, [loading, error, data, onSuccess]);
  20. return <div>Data: {data}</div>;
  21. }

问题所在:上面的代码使用了两个

  1. useEffect
,第一个用来请求异步数据,第二个用来调用回调函数。在第一个异步请求数据成功,才会触发第二个
  1. useEffect
的执行,但是,我们并不能完全保证,第二个
  1. useEffect
的依赖项完全受控于第一个
  1. useEffect
的成功请求数据。因此我们可以改造一下代码,如下代码:

推荐&radic;

  1. function DataList({ onSuccess }) {
  2. const [loading, setLoading] = useState(false);
  3. const [error, setError] = useState(null);
  4. const [data, setData] = useState(null);
  5. const fetchData = () => {
  6. setLoading(true);
  7. callApi()
  8. .then((res) => {
  9. setData(res)
  10. onSuccess()
  11. })
  12. .catch((err) => setError(err))
  13. .finally(() => setLoading(false));
  14. };
  15. useEffect(() => {
  16. fetchData();
  17. }, []);
  18. return <div>Data: {data}</div>;
  19. }

04.单一职责组件

什么时候该把一个组件分成几个更小的组件?如何构建组件树?在使用基于组件的框架时,所有这些问题每天都会出现。然而,设计组件时的一个常见错误是将两个用例组合成一个组件。

不推荐&times;

  1. function Header({ menuItems }) {
  2. return (
  3. <header>
  4. <HeaderInner menuItems={menuItems} />
  5. </header>
  6. );
  7. }
  8. function HeaderInner({ menuItems }) {
  9. return isMobile() ? <BurgerButton menuItems={menuItems} /> : <Tabs tabData={menuItems} />;
  10. }

问题所在:上面的代码通过这种方法,组件

  1. HeaderInner
试图同时成为两个不同的东西,一次做不止一件事情并不是很理想。此外,它还使得在其他地方测试或重用组件变得更加困难。因此我们可以改造一下代码,如下代码:

推荐&radic;

将条件提升一级,可以更容易地看到组件的用途,并且它们只有一个职责,即

  1. <Tabs/>
  1. <BurgerButton/>
,而不是试图同时成为两个不同的东西。
  1. function Header(props) {
  2. return (
  3. &lt;header&gt;
  4. {isMobile() ? &lt;BurgerButton menuItems={menuItems} /&gt; : &lt;Tabs tabData={menuItems} /&gt;}
  5. &lt;/header&gt;
  6. )
  7. }

05.单一职责useEffects

通过对比

  1. componentWillReceiveProps
  1. componentDidUpdate
方法,才认识到
  1. userEffect
的美丽。但是没有妥当使用useEffect也是容易出问题的。

不推荐&times;

  1. function Example(props) {
  2. const location = useLocation();
  3. const fetchData = () => {
  4. /* Calling the api */
  5. };
  6. const updateBreadcrumbs = () => {
  7. /* Updating the breadcrumbs*/
  8. };
  9. useEffect(() => {
  10. fetchData();
  11. updateBreadcrumbs();
  12. }, [location.pathname]);
  13. return (
  14. <div>
  15. <BreadCrumbs />
  16. </div>
  17. );
  18. }

问题所在:上面的

  1. useEffect
同时触发了两个副作用,但是并不都是我们需要的副作用,因此我们可以改造一下代码,如下代码:

推荐&radic;将两个副作用从一个useEffect中分离出来。

  1. function Example(props) {
  2. const location = useLocation();
  3. const fetchData = () => {
  4. /* Calling the api */
  5. };
  6. const updateBreadcrumbs = () => {
  7. /* Updating the breadcrumbs*/
  8. };
  9. useEffect(() => {
  10. updateBreadcrumbs();
  11. }, [location.pathname]);
  12. useEffect(()=>{
  13. fetchData();
  14. },[])
  15. return (
  16. <div>
  17. <BreadCrumbs />
  18. </div>
  19. );
  20. }

以上就是hooks写React组件要注意哪些细节的详细内容,更多关于hooks写React组件要注意哪些细节的资料请关注九品源码其它相关文章!