对于带有反应查询的大型反应应用程序,推荐的方法是什么?

Sim*_*low 4 typescript reactjs react-hooks react-functional-component react-query

我最近开始使用功能组件和react-query进行react,它运行良好,只是我不清楚如何正确组织组件。

我习惯设计组件的方式是使用一个顶级组件来执行所有数据访问并通过 props 将数据传递给它的子组件。它还将各种回调处理程序传递给子组件,以便在需要操作时,顶级组件将更新数据并将新数据传递给子组件。所以在我的例子中,所有对 useQuery()、useMutation() 的调用都驻留在顶级组件中,但这使代码变得极其混乱。但它很像包含各种子组件的页面,这些子组件仅显示数据或帮助用户与数据交互。

function Page(){
  const [page, setPage] = useState(1)
  const [size, setSize] = useState(10)

  const persons = useQuery('persons', async ()=> await getPersons(page, size))
  const addPerson = useMutation(async (args)=> { 
   const {id, name, desc} = args
await addPerson(id, name, description)
})
  const person = useQuery('persons', async ()=> await getOnePerson(page, size), { enabled : false })

  const addPersonCB = (id: number, name: string, desc: string)=> {
    addPerson.mutate({id, name, desc})
  }
 // complex if/else logic to choose child components 
Run Code Online (Sandbox Code Playgroud)

第二种方法是将react useQuery() 和useMutation 分散到需要的整个组件中。为了进一步简化事情,如果渲染逻辑很复杂,每个组件都会有一个父组件来执行操作并将数据作为 prop 传递。

function PersonCard(props: PersonCardPropsType){
   const {data, isLoading, isError, error} = useQuery(`personQuery${props.id}`, getPerson)

   if(isLoading)
      return <Wait />
  
   if(isError)
     return <Error reason={error} />

   const record = data as PersonModel
   return ( <PersonCardUI person={record} />) 
}
Run Code Online (Sandbox Code Playgroud)

并且可能有网格、表格等组件,每个组件都以对的形式

<PersonEditor />, <PersonEditorUI />, <PersonGrid />, <PersonGridUI /> 
Run Code Online (Sandbox Code Playgroud)

在这种情况下,调用分散在代码中的各处。我想知道

  1. 对于大型项目,建议采用哪种方法?为什么?
  2. Redux 和 React-Query 的混合搭配可以吗?例如,网格具有页面大小和页码,可能应该放入 redux 中?
  3. 在某些地方使用纯 axios/fetch 和 redux/react-query 可以吗?这被认为是一种不受欢迎的做事方式?

TkD*_*odo 11

useQuery通常认为在需要的地方使用它是最佳实践。容器/展示组件的分离虽然仍然是可能的,但自从钩子出现以来已经基本上被弃用了。使用 redux connect / mapStateToProps,这最佳实践。现在,即使在 redux 中,您也只需调用useSelectoruseDispatch靠近您需要的地方即可。这与反应查询没有什么不同。

Mark Erikson 有一篇关于这个主题的精彩演讲:Hooks、HOCs 和权衡,我完全推荐观看。

在需要的地方使用react-query钩子不仅可以避免道具钻探,还可以使react-query更容易地保持数据最新,因为更多的观察者(=调用useQuery的组件)正在安装。staleTime这也是为什么当您想要自定义重新获取行为时最好只设置 a 。我在React Query as a State Manager中详细介绍了这一点。

Redux 和 React-Query 的混合搭配可以吗?例如,网格具有页面大小和页码,可能应该放入 redux 中?

完全可以,只要你不将服务器状态同步到 redux 即可。页码和页面大小被视为“客户端状态”,因为客户端可以控制该状态。用户选择页面,服务器根据该页面响应数据。我还喜欢将其抽象到自定义挂钩中:

const useData = () => {
  const pageNumber = useSelector(state => state.pageNumber)
  return useQuery(["data", pageNumber], () => fetchData(pageNumber))
}
Run Code Online (Sandbox Code Playgroud)

这样,您就有了一个可以在任何地方使用的钩子(无需向其传递任何内容),并且如果发生更改,它会自动重新获取数据pageNumber

在某些地方使用纯 axios/fetch 和 redux/react-query 可以吗?这被认为是一种不受欢迎的做事方式?

如果您不需要为您管理缓存/加载状态等,那么当然可以。我唯一想到的我不想查询/突变的事情可能是文件下载等:)