直接看demo,在components下新建HooksDemo.js:
import React from 'react';
const MOCK_DATA = [
{
name: "zhangsan",
age: 18
},
{
name: "lisi",
age: 10
}
];
export default function HooksDemo() {
return (
<ul>
{MOCK_DATA.map(e => (
<li key={e.name}>
{e.name}---{e.age}
</li>
))}
</ul>
);
}
同样地在App.js中引入:
...
import HooksDemo from './components/HooksDemo';
function App() {
...
return (
<div>
...
<HooksDemo />
</div>
);
}
在这里做的是在前台模拟一些后台数据,这里是两个用户。
实际上请求后台是有延时的,结合前面的useState,HooksDemo.js的写法会更接近于下面这种形式:
import React, { useEffect, useState } from 'react';
const MOCK_DATA = [
{
name: "zhangsan",
age: 18
},
{
name: "lisi",
age: 10
}
];
export default function HooksDemo() {
const [users, setUsers] = useState([]);
useEffect(() => {
setTimeout(() => { // 模拟后台请求,实际上可能为axios或者ajax
setUsers(MOCK_DATA);
}, 2000);
}, []);
return users.length === 0? 'Loading!'
: (
<ul>
{users.map(e => (
<li key={e.name}>
{e.name}---{e.age}
</li>
))}
</ul>
);
}
使用randomuser这个接口,页面会更贴近真实案例(原视频cnnodejs.org我的网络打不开):
import React, { useEffect, useState } from 'react';
export default function HooksDemo() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://api.randomuser.me/?nat=US&results=2") // 2 denotes that generating 2 users.
.then(res => res.json())
.then(json => setUsers(json.results));
}, []);
return users.length === 0? 'Loading!'
: (
<ul>
{users.map(e => (
<li key={e.email}>
{e.name.first}---{e.dob.age}
</li>
))}
</ul>
);
}
效果图:
现在有一个需求,点击li的一个item,右边显示其具体的内容,比如用户id,地址什么的。
import React, { useEffect, useState } from 'react';
export default function HooksDemo() {
const [users, setUsers] = useState([]);
const [detail, setDetail] = useState("");
useEffect(() => {
fetch("https://api.randomuser.me/?nat=US&results=2") // 2 denotes that generating 2 users.
.then(res => res.json())
.then(json => setUsers(json.results));
}, []);
return users.length === 0 ? 'Loading!' :
(
<div style={{display: 'flex'}}>
<ul style={{width: 300, cursor: 'pointer'}}>
{users.map(e =>
(<li key={e.email}>{e.name.first}---{e.dob.age}</li>))
}
</ul>
<div>
{detail}
</div>
{/* <div dangerouslySetInnerHTML={{__html: xxxhtmlstring}}></div> */}
</div>
)
}
假如这里的detail也需要fetch后复制。就会把useEffect里弄得挺臃肿。如果想把users这个state单独拿出来定义成一个hooks,就可以这样定义。
新建hooks目录并在里面建立一个useUsers.js,注意使用use开头,其内容如下:
import {useState, useEffect} from 'react';
export default function useUsers() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://api.randomuser.me/?nat=US&results=2") // 2 denotes that generating 2 users.
.then(res => res.json())
.then(json => setUsers(json.results));
}, []);
return users; // array or object
}
其实就是把users初始化及初始设置的部分搬过来。HooksDemo也跟着变:
import React, { useState } from 'react';
import useUsers from "../hooks/useUsers";
export default function HooksDemo() {
const users = useUsers();
const [detail] = useState("");
return users.length === 0 ? 'Loading!' :
(
<div style={{display: 'flex'}}>
<ul style={{width: 300, cursor: 'pointer'}}>
{users.map(e =>
(<li key={e.email}>{e.name.first}---{e.dob.age}</li>))
}
</ul>
<div>
{detail}
</div>
{/* <div dangerouslySetInnerHTML={{__html: xxxhtmlstring}}></div> */}
</div>
)
}
这样就演示了自定义useHooks的最基本的用法,感觉还不是很具体,后续有更新的话将补充。
原视频演示的是setDetail是在fetchuser后根据user的id再次fetch的,这是嵌套异步调用。我自己稍微改了下,变成换头像,大概效果就是点击列表的某一项,右边显示该用户的头像,但是detail的初始化没做好。
感兴趣的可以 参考源码