- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章使用hooks写React组件需要注意的5个地方由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
Hook是React16.8开始新增的特性。虽然React官方文档已经作出了针对React hooks的相关概念的讲解,但是光看官方文档是很难将hooks使用好的,在编写hooks的过程中很容易跳进陷阱和错误。本文总结了5个不好的地方.
在函数组件中我们可以使用useState来管理状态,这使得对状态的管理变得很简单,但是也容易被滥用,我们通过下面的代码样例看下容易忽略的地方.
不推荐× 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
function
ClickButton(props){
const [count, setCount] = setState(0)
const onClickCount = () => {
setCount((c) => c + 1)
}
const onClickRequest = () => {
apiCall(count)
}
return
(
<div>
<button onClick={onClickCount}>Click</button>
<button onClick={onClickRequest}>Submit</button>
</div>
)
}
|
问题所在:仔细看上面的代码,乍一看其实也没什么问题,点击按钮更新 count。但是问题也就出在这里,我们的 return 部分并没有用到 count 状态,而每次 setCount 都会使组件重新渲染一次,而这个渲染并不是我们需要的,多出来的渲染会使得页面的性能变差,因此我们可以改造一下代码,如下代码:
推荐√ 如果我们只是单纯的想要一个能在组件声明周期内保存的变量,但是变量的更新不需要组件的重新渲染,我们可以使用 useRef 钩子.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
function
ClickButton(props){
const count = useRef(0)
const onClickCount = () => {
count.current++
}
const onClickRequest = () => {
apiCall(count.current)
}
return
(
<div>
<button onClick={onClickCount}>Click</button>
<button onClick={onClickRequest}>Submit</button>
</div>
)
}
|
在React SPA应用中,我们用react-router来处理路由的跳转,我们很经常在组件中写了一个按钮,通过点击按钮的事件来处理路由的跳转,如下代码:
不推荐× 。
1
2
3
4
5
6
7
|
function
ClickButton(props){
const history = useHistory()
const onClickGo = () => {
history.push(
'/where-page'
)
}
return
<button onClick={onClickGo}>Go to where</button>
}
|
问题所在:尽管上述代码可以正常工作,但是却不符合Accessibility(易访问性设计)的要求,此类按钮并不会被屏幕阅读器当作一个可以跳转的链接。因此我们可以改造一下代码,如下代码:
推荐√ 。
1
2
3
4
5
|
function
ClickButton(props){
return
<Link to=
"/next-page"
>
<span>Go to where</span>
</Link>
}
|
有时候,我们只想在 React 更新 DOM 之后运行一些额外的代码。比如发送网络请求,手动变更 DOM,记录日志.
不推荐× 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
function
DataList({ onSuccess }) {
const [loading, setLoading] = useState(
false
);
const [error, setError] = useState(
null
);
const [data, setData] = useState(
null
);
const fetchData = () => {
setLoading(
true
);
callApi()
.then((res) => setData(res))
.
catch
((err) => setError(err))
.finally(() => setLoading(
false
));
};
useEffect(() => {
fetchData();
}, []);
useEffect(() => {
if
(!loading && !error && data) {
onSuccess();
}
}, [loading, error, data, onSuccess]);
return
<div>Data: {data}</div>;
}
|
问题所在:上面的代码使用了两个useEffect ,第一个用来请求异步数据,第二个用来调用回调函数。在第一个异步请求数据成功,才会触发第二个 useEffect 的执行,但是,我们并不能完全保证,第二个 useEffect 的依赖项完全受控于第一个 useEffect 的成功请求数据。因此我们可以改造一下代码,如下代码:
推荐√ 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
function
DataList({ onSuccess }) {
const [loading, setLoading] = useState(
false
);
const [error, setError] = useState(
null
);
const [data, setData] = useState(
null
);
const fetchData = () => {
setLoading(
true
);
callApi()
.then((res) => {
setData(res)
onSuccess()
})
.
catch
((err) => setError(err))
.finally(() => setLoading(
false
));
};
useEffect(() => {
fetchData();
}, []);
return
<div>Data: {data}</div>;
}
|
什么时候该把一个组件分成几个更小的组件?如何构建组件树?在使用基于组件的框架时,所有这些问题每天都会出现。然而,设计组件时的一个常见错误是将两个用例组合成一个组件.
不推荐× 。
1
2
3
4
5
6
7
8
9
10
11
|
function
Header({ menuItems }) {
return
(
<header>
<HeaderInner menuItems={menuItems} />
</header>
);
}
function
HeaderInner({ menuItems }) {
return
isMobile() ? <BurgerButton menuItems={menuItems} /> : <Tabs tabData={menuItems} />;
}
|
问题所在:上面的代码通过这种方法,组件HeaderInner试图同时成为两个不同的东西,一次做不止一件事情并不是很理想。此外,它还使得在其他地方测试或重用组件变得更加困难。因此我们可以改造一下代码,如下代码:
推荐√ 。
将条件提升一级,可以更容易地看到组件的用途,并且它们只有一个职责,即<Tabs/>或<BurgerButton/>,而不是试图同时成为两个不同的东西.
1
2
3
4
5
6
7
|
function
Header(props) {
return
(
<header>
{isMobile() ? <BurgerButton menuItems={menuItems} /> : <Tabs tabData={menuItems} />}
</header>
)
}
|
通过对比componentWillReceiveProps或componentDidUpdate方法,才认识到userEffect的美丽。但是没有妥当使用useEffect也是容易出问题的.
不推荐× 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
function
Example(props) {
const location = useLocation();
const fetchData = () => {
/* Calling the api */
};
const updateBreadcrumbs = () => {
/* Updating the breadcrumbs*/
};
useEffect(() => {
fetchData();
updateBreadcrumbs();
}, [location.pathname]);
return
(
<div>
<BreadCrumbs />
</div>
);
}
|
问题所在:上面的useEffect同时触发了两个副作用,但是并不都是我们需要的副作用,因此我们可以改造一下代码,如下代码:
推荐√ 。
将两个副作用从一个useEffect中分离出来.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
function
Example(props) {
const location = useLocation();
const fetchData = () => {
/* Calling the api */
};
const updateBreadcrumbs = () => {
/* Updating the breadcrumbs*/
};
useEffect(() => {
fetchData();
updateBreadcrumbs();
}, [location.pathname]);
return
(
<div>
<BreadCrumbs />
</div>
);
}
|
Five common mistakes writing react components (with hooks) in 2020 。
以上就是使用hooks写React组件需要注意的5个地方的详细内容,更多关于hooks写React组件的资料请关注我其它相关文章! 。
原文链接:https://juejin.cn/post/6947573426076778533 。
最后此篇关于使用hooks写React组件需要注意的5个地方的文章就讲到这里了,如果你想了解更多关于使用hooks写React组件需要注意的5个地方的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我创建了一个简单的钩子(Hook),我安装了它 SetWindowsHookEx(WH_CBT, addr, dll, 0); 完成后,我卸载 UnhookWindowsHookEx(0); 然后我可
我正在使用 React Hooks,当我用 mobx 的观察者包装我的组件时,我收到了这个错误。可能是什么问题?是否可以将 mobx 与 React Hooks 一起使用? import classn
我知道这个问题已经被回答过很多次了。我只是找不到解决我的问题的答案,让我相信,我要么是愚蠢的,要么是我的问题没有被解决,因为它比我更愚蠢。除此之外,这是我的问题: 我正在尝试创建一个功能组件,它从 r
我正在使用 React Navigation 的 useNavigation 钩子(Hook): 在 MyComponent.js 中: import { useNavigation } from "
我想在 gitlab 中使用预提交钩子(Hook)。我做的一切都像文档中一样:https://docs.gitlab.com/ce/administration/custom_hooks.html 在
我最近在和一些人谈论我正在编写的程序时听到了“hook”这个词。尽管我从对话中推断出钩子(Hook)是一种函数,但我不确定这个术语到底意味着什么。我搜索了定义,但找不到好的答案。有人可以让我了解这个术
我正在寻找一个在页面创建或页面更改后调用的钩子(Hook),例如“在导航中隐藏页面”、“停用页面”或“移动/删除页面“ 有人知道吗? 谢谢! 最佳答案 这些 Hook 位于 t3lib/class.t
我正在使用钩子(Hook)将新方法添加到 CalEventLocalServiceImpl 中... 我的代码是.. public class MyCalendarLocalServiceImpl e
编译器将所有 SCSS 文件编译为 STANDALONE(无 Rails)项目中的 CSS 后,我需要一个 Compass Hook 。 除了编辑“compiler.rb”(这不是好的解决方案,因为
我“.get”一个请求并像这样处理响应: resp = requests.get('url') resp = resp.text .. # do stuff with resp 阅读包的文档后,我看到
我们想在外部数据库中存储一些关于提交的元信息。在克隆或 checkout 期间,应引用此数据库,我们将元信息复制到克隆的存储库中的文件中。需要数据库而不是仅仅使用文件是为了索引和搜索等...... 我
我有一个 react 钩子(Hook)useDbReadTable,用于从接受tablename和query初始数据的数据库读取数据。它返回一个对象,除了数据库中的数据之外,还包含 isLoading
在下面的代码中,当我调用 _toggleSearch 时,我同时更新 2 个钩子(Hook)。 toggleSearchIsVisible 是一个简单的 bool 值,但是,setActiveFilt
问题 我想在可由用户添加的表单中实现输入字段的键/值对。 参见 animated gif on dynamic fields . 此外,我想在用户提交表单并再次显示页面时显示保存的数据。 参见 ani
当状态处于 Hook 状态时,它可能会变得陈旧并泄漏内存: function App() { const [greeting, setGreeting] = useState("hello");
const shouldHide = useHideOnScroll(); return shouldHide ? null : something useHideOnScroll 行为应该返回更新后
我正在使用 React-native,在其中,我有一个名为 useUser 的自定义 Hook,它使用 Auth.getUserInfro 方法从 AWS Amplify 获取用户信息,并且然后获取返
我正在添加一个 gitolite 更新 Hook 作为 VREF,并且想知道是否有办法将它应用于除 gitolite-admin 之外的所有存储库。 有一个更简单的方法而不是列出我想要应用 Hook
如何使用带有 react-apollo-hooks 的 2 个 graphql 查询,其中第二个查询取决于从第一个查询中检索到的参数? 我尝试使用如下所示的 2 个查询: const [o, setO
我是 hooks 的新手,到目前为止印象还不错,但是,如果我尝试在函数内部使用 hooks,它似乎会提示(无效的 hook 调用。Hooks can only be called inside o
我是一名优秀的程序员,十分优秀!