V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Parker0
V2EX  ›  React

React 小白学习过程中遇到技术问题

  •  1
     
  •   Parker0 · 2023-03-05 18:01:03 +08:00 · 3586 次点击
    这是一个创建于 608 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在学习 React ,还在 CRUD 阶段,目前遇到一个问题,没找到什么原因,还望大佬们指点一二

    主要的问题就是我每次刷新页面,projects 和 users 接口都被调用了两次

    嵌套结构是 <App> <ProjectListPage> </App>

    以下是 ProjectListPage 组件的代码,只有这个组件有处理各种状态,其他两个组件 SeachPanel 、List 都没有状态的处理

    import React, {useEffect, useState} from "react";
    import {SeachPanel} from "./search-panel";
    import {List} from "./list";
    import {cleanObject, uesMount} from "../../utils";
    import qs from "qs";
    
    const apiUrl = 'http://localhost:3001'
    export const ProjectListPage = () =>{
     
        const [param,setParam] = useState({
            name: '',
            personId: ''
        })
    
        const [list,setList] = useState([])
    
        // 当搜索内容改变的时候从新获取列表(默认会先执行一次)
        useEffect(()=>{
            fetch(`${apiUrl}/projects?${qs.stringify(cleanObject(param))}`).then(async (resp) => {
                if (resp.ok) {
                    setList(await resp.json())
                }
            })
        },[])
    
        // option 用户状态
        const [users,setUsers] = useState([])
        useEffect(()=>{
            fetch(`${apiUrl}/users`).then(async (resp) => {
                if (resp.ok) {
                    setUsers(await resp.json())
                }
            })
        },[])
    
        return <div>
            <SeachPanel users={users} param={param} setParam={setParam}/>
            <List users={users} list={list}/>
        </div>
    }
    
    15 条回复    2023-03-06 09:34:41 +08:00
    Leviathann
        2
    Leviathann  
       2023-03-05 18:10:22 +08:00   ❤️ 2
    strictMode 默认行为就是在开发模式下调用两次 useEffect
    意思就是仅调用一次并不是 useEffect 定义的行为,只是目前是这么实现的,以后可能会改
    调用两次的目的就是让你不要依赖 useEffect 的行为,而是显式声明一个标记值,根据标记值决定是否要执行
    Parker0
        3
    Parker0  
    OP
       2023-03-05 18:29:18 +08:00
    @Satelli
    @Leviathann
    了解,感谢两位大佬,问题已解决!
    huijiewei
        4
    huijiewei  
       2023-03-05 19:43:31 +08:00
    用 swr
    beginor
        5
    beginor  
       2023-03-05 19:50:47 +08:00 via Android   ❤️ 3
    建议结合 react-router , 把加载数据 /保存数据之类的操作都写在路由的 loader 和 action 里面,jsx 只做界面, 这样逻辑清晰很多, 可以看下 react-router 官方的 tutorial

    https://reactrouter.com/en/main/start/tutorial
    july1995
        6
    july1995  
       2023-03-05 22:59:16 +08:00 via iPhone
    2 楼正解
    Parker0
        7
    Parker0  
    OP
       2023-03-05 23:11:57 +08:00
    @beginor 谢谢,我还没学到这呢。。比较前期,目前学到就是用这个来加载数据
    sjhhjx0122
        8
    sjhhjx0122  
       2023-03-05 23:20:07 +08:00
    后面 react 应该会出个叫 use 的 api 配合 Suspense 就不需要在 useEffect 里发请求了
    beginor
        9
    beginor  
       2023-03-05 23:49:13 +08:00
    @sjhhjx0122 使用新版本 react-router 中的 data router , 已经不需要在 useEffect 中发送请求了
    Parker0
        10
    Parker0  
    OP
       2023-03-05 23:53:33 +08:00
    学完哪些东西再学 react-router?
    @beginor
    himself65
        11
    himself65  
       2023-03-06 03:32:20 +08:00 via iPhone
    React 18.3.0 出了 OffScreen 组件之后,useEffect 不再保证空 deps 下只调用一次了,StrictMode 就是让告诉你不要瞎用这个 hook
    yikyo
        12
    yikyo  
       2023-03-06 05:11:17 +08:00 via iPhone
    react 心智负担重,开发环境还要强制执行两次

    第二个要吐槽 react router 每次版本更新就是破环性更新,一个路由库更新策略很奇怪,准备换 tanstack router
    hengshenyu
        13
    hengshenyu  
       2023-03-06 08:30:28 +08:00
    这儿实际是需要在下次执行 effect 的时候需要 AbortController 取消上一次的接口处理,需要大量的模板,不用请求库麻烦的很
    ibegyourpardon
        14
    ibegyourpardon  
       2023-03-06 09:22:49 +08:00
    不使用 react-router ,使用状态管理如 zustand 之类,把数据获取和对数据的二次加工等放进去也是个不错的选择。
    beginor
        15
    beginor  
       2023-03-06 09:34:41 +08:00
    @Parker0 学完基本的那几个 hooks 就可以开始学了,路由而已,肯定要切换页面的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1074 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:38 · PVG 03:38 · LAX 12:38 · JFK 15:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.