发布于 2026-01-06 4 阅读
0

在 LSD 3 中使用 React Hooks 进行抽象。最后一个示例是 useBusinessLogic Hook。

使用 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
    }
}
Enter fullscreen mode Exit fullscreen mode

如果需要修改某些内容,我们只需修改这个小函数,只要它返回相同的对象,就能在任何地方正常工作。现在,我们只需一行代码就能在任何地方使用它。

const App = () => {
    const { todos, isLoading, error } = useTodos()

    // other stuff
}
Enter fullscreen mode Exit fullscreen mode

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 }]
}
Enter fullscreen mode Exit fullscreen mode

等等,我们还需要更新 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 }
}
Enter fullscreen mode Exit fullscreen mode

在我们的代码中,useToggleTodo我们可以使用useMutationreact-query这样每当我们切换待办事项时,待办事项查询都会重新获取。

import { useMutation } from "react-query"

const getToggleTodoById = todoId => axios.get(`/api/todos/${todoId}/toggle`)

const useToggleTodo = () => {
    return useMutation(getToggleTodoById, { refetchQueries: ["todos"] })
}
Enter fullscreen mode Exit fullscreen mode

看看我们是如何只用了react-query几秒钟就迁移到使用原生 axios 的,而且只需要修改几行代码。现在,我们的组件也有了这些方便的钩子。

朋友们,这就是我们使用钩子并像专业人士一样进行管理的方法(至少据我所知是这样)。现在,如果你有朋友,就可以去向他们炫耀你的新玩意儿了

文章来源:https://dev.to/patheticgeek/abstracting-with-react-hooks-on-lsd-15p