• 🐑
    置顶
    2022-09-19 来自北京
    你好,我是《现代React Web开发实战》的编辑辰洋,这是👇项目的源代码链接,供你学习与参考:https://gitee.com/evisong/geektime-column-oh-my-kanban/releases/tag/v0.10.0
    共 1 条评论
    
  • 学习前端-react
    2022-09-14 来自北京
    请问:use Effect 的执行是可以拿到真实dom的,那为啥在图中提交阶段却是在真实dom之前?

    作者回复: 你好,学习前端-react,抱歉这几天在赶稿回复晚了。 你说得对。useEffect的副作用回调和清除函数,它们都在提交阶段执行,且大多情况都是异步执行的。这些函数被加入callback更新队列。在真实DOM绘制之后,下一次React渲染之前,这个队列里的callback会依次执行,所以这时候callback能拿到真实DOM。 这张图在第一次画时,只画了同步执行的情况,给大家造成了误解,还请见谅。目前图片已经做了更新,依然省略了一些实现细节,但更贴近实际情况了,请以这一版为准。

    共 3 条评论
    2
  • 船长
    2022-09-21 来自北京
    不是很理解 useMemo 那个例子,比如用 下面这个useEffect 写法不是也可以持久化记忆数据吗?好像只是比 useMemo 那种写法多了个 setXXX 所造成的一次渲染? const [num, setNum] = useState("0"); const [num2, setNum2] = useState("0"); useEffect(() => { const n = parseInt(num, 10); setNum2(fibonacci(n)); }, [num]);

    作者回复: 你好,船长,从实现功能来讲你用useState+useEffect代替useMemo是可行的。正如你说的,确实多了一次渲染。具体来说,useMemo的回调是在渲染过程中执行,而useEffect的回调会在提交阶段执行,useEffect回调内部调用了useState的话,会触发一次新的渲染。从用户感知上应该没太大差别,毕竟渲染过程是异步的,useEffect的回调也是异步的。 在实际项目中,我们可能会遇到连续在一个组件中写十来个Hooks的情况,每当存在这种跨多次渲染还相关的Hooks,都会多少增加一些调试的难度。

    共 2 条评论
    1
  • 满眼星🌟 辰🍊
    2022-09-16 来自北京
    图例中,useLayoutEffect是同步更新dom,应该在useEffect之前执行,不是吗

    作者回复: 你好,满眼星辰,抱歉这几天在赶稿回复晚了。 你说得对。useEffect记录的副作用回调和清除函数,都在提交阶段执行,且大多情况都是异步执行的。这些函数被加入callback更新队列。在真实DOM绘制之后,下一次React渲染之前,队列里的callback会依次执行。 在第一次画图例时,只画了同步执行的情况,给你造成了误解,还请见谅。目前图片已经做了更新,依然省略了一些实现细节,但更贴近实际情况了,请以这一版为准。

    
    
  • 都市夜归人
    2022-09-16 来自北京
    其实这两个 Hooks 与 useEffect 并不沾亲带故。且不说它们的用途完全不同,单从回调函数的执行阶段来看,前者是在渲染阶段执行,而后者是在提交阶段。 这句话与上面的生命周期图不太一致,求解惑

    作者回复: 你好,都市夜归人,这两周我都在赶稿,抱歉回复晚了。这里所指的“回调函数”,对于: const memoized = useMemo(() => createByHeavyComputing(a, b), [a, b]); 指的是其中的() => createByHeavyComputing(a, b),同时也叫工厂函数; 对于 const memoizedFunc = useCallback(() => {if (a) b()}, [a, b]); 指的是() => {if (a) b()}; () => createByHeavyComputing(a, b) 和 () => {if (a) b()} 如果符合执行条件的话,会在渲染阶段执行。 对于 useEffect(() => { if (province === '山东') { setCities(['济南', '青岛', '淄博']); }}, [province]); 指的是 () => { if (province === '山东') { setCities(['济南', '青岛', '淄博']); }} 如果符合执行条件的话,() => { if (province === '山东') { setCities(['济南', '青岛', '淄博']); }} 会在提交阶段执行。

    共 2 条评论
    
  • 都市夜归人
    2022-09-15 来自北京
    const KanbanCard = ({ title, status }) => { const [displayTime, setDisplayTime] = useState(status); useEffect(() => { const updateDisplayTime = () => { const timePassed = new Date() - new Date(status); let relativeTime = '刚刚'; // ...省略 setDisplayTime(relativeTime); }; const intervalId = setInterval(updateDisplayTime, UPDATE_INTERVAL); updateDisplayTime(); return function cleanup() { clearInterval(intervalId); }; }, [status]); 可以看到,useEffect 接收了副作用回调函数和依赖值数组两个参数,其中副作用回调函数的返回值也是一个函数,这个返回的函数叫做清除函数。组件在下一次提交阶段执行同一个副作用回调函数之前,或者是组件即将被卸载之前,会调用这个清除函数。 没有看懂,上面的哪有两个参数啊?
    展开

    作者回复: 你好,都市夜归人,抱歉这两周在赶稿回复晚了。这里说的是useEffect的两个参数。 const KanbanCard = ({ title, status }) => { const [displayTime, setDisplayTime] = useState(status); 这段代码只是为了提示一下useEffect所在的相对位置。 下面的: useEffect(() => { // ... return function cleanup() { // ... }; }, [status]); 中的: () => { // ... return function cleanup() { // ... }; } 就是useEffect第一个参数,称作副作用回调函数(Effect Callback); 而后面的: [status] 就是第二个参数,称作依赖值数组(Dependencies)。

    共 4 条评论
    
  • Imart
    2022-11-15 来自广东
    useEffect 是在浏览器渲染/呈现dom内容后执行的; useLayoutEffect 是在真实dom更新后,浏览器渲染dom内容前执行的,即在render函数执行后,接着同步马上执行回调函数内容;
    
    1
  • Socrakit
    2023-07-12 来自江苏
    我试图在 handleSubmit 里调用 handleSaveAll(),希望每次新增“待处理” 后自动保存,但失败了。调用 handleSaveAll 的时候 todoList 还没有被更新,第二次新增后才会把第一次新增的保存进去,这是为什么呢 ? const handleSubmit = (title) => { const d = new Date() const n = d.toLocaleDateString().replace('/', '-') + ' ' + d.toLocaleTimeString(); setTodoList(currentTodoList => [ { title, dt: n}, ...currentTodoList ]); handleSaveAll() };
    
    
  • Geeker
    2022-11-04 来自浙江
    个人觉得框架不应该把“负担” 甩给用户
    
    