三步学会 React(Vuer 必看)

33 阅读2分钟

三步学会 React(Vue 开发者视角)

如果你已经有 Vue 的开发经验,并且初步了解过 React,那么这篇文章将帮你快速上手 React 的核心使用方式。


第一关:理解数据的异步更新

在 Vue 中,数据更新是同步的:你修改了数据,紧接着使用它,拿到的一定是最新值。  

而在 React 中,状态更新是异步的,如果你在 setState 后立即读取状态,拿到的还是旧值。

我们通过一个“年级成绩查询”的多级筛选表单来理解这个问题。

需求描述

  • 一级筛选:选择年级(一年级 ~ 六年级)

  • 二级筛选:选择学科(不同年级对应不同学科)

  • 每次筛选变动,都要实时查询对应学生列表


Vue 实现(正常)


<template></template>

<script setup>

  const searchParams = reactive({
    grade: undefined,
    subject: undefined,
  });

  const searchOptions = reactive({
    grade: [],
    subject: [],
  });

  const studentList = ref([]);
  
  const init = () => {
    getGradeListApi().then(res => {
      searchOptions.grade = res;
      gradeChange(res[0].value);
    });
  };

  init();

  const gradeChange = value => {
    searchParams.grade = value;
    getSubjectListApi({ grade: searchParams.grade }).then(res => {
      searchOptions.subject = res;
      subjectChange(res[0].value);
    });
  };


  const subjectChange = value => {
    searchParams.subject = value;
    getStudentListApi({
      grade: searchParams.grade,
      subject: searchParams.subject,
    }).then(res => {
      studentList.value = res;
    });
  };
</script>


React 实现(❌ 有问题的版本)

import { useEffect, useState } from "react";

function App() {

  const [searchParams, setSearchParams] = useState({
    grade: undefined,
    subject: undefined,
  });


  const [searchOptions, setSearchOptions] = useState({
    grade: [],
    subject: [],
  });

  const [studentList, setStudentList] = useState([]);

  useEffect(() => {
    getGradeListApi().then(res => {
      setSearchOptions(prev => ({ ...prev, grade: res }));
      gradeChange(res[0].value);
    });
  }, []);

  const gradeChange = v => {
    setSearchParams(prev => ({ ...prev, grade: v }));
    getSubjectListApi({ grade: searchParams.grade }).then(res => {
      setSearchOptions(prev => ({ ...prev, subject: res }));
      subjectChange(res[0].value);
    });
  };

  const subjectChange = v => {
    setSearchParams(prev => ({ ...prev, subject: v }));
    getStudentListApi({
      grade: searchParams.grade,
      subject: searchParams.subject,
    }).then(res => {
      setStudentList(res);
    });
  };

  return <></>;
}

export default App;


问题出在哪?

gradeChange 中,我们调用了 setSearchParams 更新年级,但紧接着在请求学科列表时,searchParams.grade 仍然是旧值。  

这就是 React 状态更新的异步性导致的典型问题。


解决方案

有两种常见的解决思路:

方法一:传递最新状态(不推荐)

在每次状态更新时,手动将最新值传给后续函数:

const gradeChange = v => {
  const newParams = { ...searchParams, grade: v };
  setSearchParams(newParams);  
  getSubjectListApi({ grade: v }).then(res => {
    setSearchOptions(prev => ({ ...prev, subject: res }));
    subjectChange(res[0].value, newParams);
  });
};

这种方式虽然可行,但容易遗漏传递参数,导致状态不一致。


方法二:使用 useEffect 监听状态变化(✅ 推荐)

将依赖状态的操作放到 useEffect 中,确保使用的是最新状态:

useEffect(() => {
  if (searchParams.grade && searchParams.subject) {
    getStudentListApi({
      grade: searchParams.grade,
      subject: searchParams.subject,
    }).then(setStudentList);
  }
}, [searchParams.grade, searchParams.subject]);

这样,每当 searchParams.gradesearchParams.subject 更新时,都会自动触发最新的查询。


小结

  • React 中状态更新是异步的,不要在 setState 后立即依赖该状态。
  • 推荐使用 useEffect ,确保使用的是最新状态。
  • 对于 Vue 转 React 的开发者来说,这是第一个需要跨越的“实战坑”。

希望这篇文章能帮你顺利迈出 React 实战的第一步!

如果对你有帮助的话,请点个赞吧!谢谢!