使用 React Hooks 在 LSD 上进行抽象
3. 最后一个,useBussinessLogic钩子
3. 最后一个,useBussinessLogic钩子
钩子函数是免费的。也就是说,你可以非常轻松地创建它们,唯一的成本就是抽象的成本。
3.1 基本useTodos钩子
现在,我们的组件并非总是只与本地状态交互,大多数时候它们会与服务器端的状态交互并管理异步操作。而这正是界限变得模糊的地方。那么,我们何不试试看,看看有没有什么办法能帮到我们呢?
我们以一个基本的待办事项应用程序为例,你会有一个待办事项列表,调用 API 来获取所有这些有趣的东西,所以让我们在一个钩子中提取它。
const useTodos = () => {
const todos = useTodosStore()
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState(null)
const fetchTodos = useCallback(async () => {
setIsLoading(true)
try {
const { data: todos } = await axios.get("/api/todos")
setTodos(todos)
setError(null)
} catch(e) {
setError(e)
}
setIsLoading(false)
})
useEffect(() => {
fetchTodos()
}, [fetchTodos])
return {
todos,
fetch: fetchTodos,
isLoading: false,
error: null
}
}
如果需要修改某些内容,我们只需修改这个小函数,只要它返回相同的对象,就能在任何地方正常工作。现在,我们只需一行代码就能在任何地方使用它。
const App = () => {
const { todos, isLoading, error } = useTodos()
// other stuff
}
3.2 修改待办事项
现在,假设我们想要切换待办事项的状态。我们该怎么做呢?我们只需把手伸进自定义的哆啦A梦口袋里,然后拿出来即可。useToggleTodo
const useToggleTodos = () => {
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState(null)
const toggleTodo = useCallback(async todoId => {
setIsLoading(true)
try {
const { data } = await axios.get(`/api/todos/${todoId}/toggle`)
setError(null)
setIsLoading(false)
return data
} catch(e) {
setError(e)
}
setIsLoading(false)
})
return [toggleTodo, { isLoading, error }]
}
等等,我们还需要更新 store 里的内容,还有,如果存在多个 useTodos 实例怎么办?我们使用的是全局 store 还是所有实例都单独更新?竞态条件怎么办?缓存呢?
3.3 一切都做得很好
记住,我们的自定义钩子也可以使用其他钩子,所以让我们从react-query引入useQuery。
import { useQuery } from "react-query"
const fetchTodos = () => axios.get('/api/todos').then(res => res.data())
const useTodos() => {
const { data: todos, isLoading, error } = useQuery('todos', fetchTodos)
return { todos, isLoading, error }
}
在我们的代码中,useToggleTodo我们可以使用useMutation,react-query这样每当我们切换待办事项时,待办事项查询都会重新获取。
import { useMutation } from "react-query"
const getToggleTodoById = todoId => axios.get(`/api/todos/${todoId}/toggle`)
const useToggleTodo = () => {
return useMutation(getToggleTodoById, { refetchQueries: ["todos"] })
}
看看我们是如何只用了react-query几秒钟就迁移到使用原生 axios 的,而且只需要修改几行代码。现在,我们的组件也有了这些方便的钩子。
朋友们,这就是我们使用钩子并像专业人士一样进行管理的方法(至少据我所知是这样)。现在,如果你有朋友,就可以去向他们炫耀你的新玩意儿了。
文章来源:https://dev.to/patheticgeek/abstracting-with-react-hooks-on-lsd-15p