You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Bootstrap Form.Control默认值未生效问题咨询及改进建议

问题描述

我正在实现点击按钮弹窗为指定学生添加成绩的功能,但遇到一个问题:直接选择下拉框默认显示的“不及格(Poor)”成绩时,该值无法被识别,没办法添加到学生成绩表(数据取自student.firstSemester);但切换到其他成绩再切回“不及格”时就能正常工作。作为开发新手,求改进方案。

相关代码

const GradesTable= ({selectedClass, displayedSubj}) => {
    let students = selectedClass.students;
    const {t} = useTranslation();
    const [isInEditMode, updateIsInEditMode] = useState(false);
    const secondTermStartsAt = new Date('2021-02-01T22:00:00.000+0000');
    const [currentUser, updateUser] = useState(null);
    const [isOpenModal, openModal] = useState(false);
    const [studentNames, setStudentNames] = useState(undefined);
    const [studentGrade, setGrade] = useState(undefined);
    const [description, setDescription] = useState(undefined);

    let allGrades = [
        {key : "2", name : t('journal table.grades.poor')},
        {key : "3", name : t('journal table.grades.average')},
        {key : "4", name : t('journal table.grades.good')},
        {key : "5", name : t('journal table.grades.very good')},
        {key : "6", name : t('journal table.grades.excellent')},
    ];

    const setOpenModal = (value, names) => {
        openModal(value);
        setStudentNames(names);
    }

    useEffect(
        () => {
            if(!currentUser){
                const user = AuthService.getCurrentUser();

                if (user) {
                    updateUser(user);
                }
            }

            if(displayedSubj && students){
                setTableData(populateTableData(students));
            }},
        [displayedSubj, students, currentUser]
    );

    const flatmapArr = (arr) => {
        return [].concat.apply([],arr);
    }

    const saveGrade = (value) => {
        var grade = {
            id: null,
            date: new Date(),
            description: description,
            mark: studentGrade,
            subject: getCurrentSubject(),
            byWhom: currentUser.teacher
        };
        
        var currentStudent = tableData.filter(student => student.names === studentNames)[0];
        var student = students.filter(stud => stud.id === currentStudent.id);
        student[0].grades.push(grade);
        try {
            StudentService.updateStudent(student[0]);
        } catch(error) {
            alert(error.stack);
        }
        setOpenModal(false);
    }

    const handleGradeChange = (grade) => {
        setGrade(grade);
        assignGradeValueToStudent(grade);
    }
  
    const assignGradeValueToStudent = (grade) => {
        var currentStudent = tableData.filter(student => student.names === studentNames)[0];
        if(isEmpty(currentStudent.firstSemester)) {
            currentStudent.firstSemester = currentStudent.firstSemester + grade;
        } else if(currentStudent.firstSemester.substring(currentStudent.firstSemester.length-1, currentStudent.firstSemester.length) === studentGrade) {
            currentStudent.firstSemester = currentStudent.firstSemester.substring(0, (currentStudent.firstSemester.length-1));
            if(isEmpty(currentStudent.firstSemester)) {
                currentStudent.firstSemester = currentStudent.firstSemester + grade;
            } else {
                currentStudent.firstSemester = currentStudent.firstSemester + " " + grade;
            }
        } else {
            currentStudent.firstSemester = currentStudent.firstSemester + " " + grade;
        }
    }

    const setCloseModal = () => {
        debugger;
        var currentStudent = tableData.filter(student => student.names === studentNames)[0];
        if(!isEmpty(currentStudent.firstSemester)) {
            currentStudent.firstSemester = currentStudent.firstSemester.substring(0, (currentStudent.firstSemester.length-1));
        }
        setOpenModal(false, undefined);
    }

    return(
        <div>
            {isOpenModal && 
                <Modal.Dialog>
                    <Modal.Header>
                        <Modal.Title>
                            {t('journal table.adding a grade')} <b><i>{studentNames}</i></b>
                        </Modal.Title>
                    </Modal.Header>

                    <Modal.Body>
                        <Form.Row>
                        <Form.Group as={Col} md="3" controlId="empty" />
                        <Form.Group as={Col} md="6" controlId="exampleForm.ControlSelect1">
                                <Form.Label>{t('journal table.grade')}</Form.Label>
                                <Form.Control
                                name='grade' 
                                as="select" 
                                defaultValue={''}
                                onChange={(event) => handleGradeChange(event.target.value)}>
                                    {allGrades && allGrades.map(grade => 
                                        <option key={grade.key} value={grade.key}>
                                            {grade.name}
                                        </option>
                                    )}
                                </Form.Control>
                            </Form.Group>
                        </Form.Row>

                        <Form.Row>
                            <Form.Group as={Col} md="2" controlId="empty" />
                            <Form.Group as={Col} md="8" controlId="exampleForm.ControlInput1">
                                <Form.Label>{t('journal table.description')}</Form.Label>
                                <Form.Control
                                name='description'
                                type="text"
                                onChange={(event) => setDescription(event.target.value)}/>
                            </Form.Group>
                        </Form.Row>

                    </Modal.Body>

                    <Modal.Footer>
                        <Button variant="secondary" onClick={() => setCloseModal(false, undefined)}>
                            {t('journal table.close')}
                        </Button>
                        <Button variant="primary" onClick={(val) => saveGrade(val)}>
                            {t('journal table.save changes')}
                        </Button>
                    </Modal.Footer>
                </Modal.Dialog>
            }
            {!isOpenModal &&
                <div>
                    <BootstrapTable
                        keyField="id"
                        data={tableData}
                        columns={columns}
                        hover
                    />
                </div>
            }
        </div>
    );
}

export default GradesTable;
解决方案

问题根源

下拉框的defaultValue设为'',但页面加载时下拉框默认渲染第一个选项(值为"2"的“不及格”),由于defaultValue不匹配任何选项的value,不会触发onChange事件,导致studentGrade状态始终是初始的undefined,直接保存时拿不到有效成绩值。切换选项后会触发onChange更新状态,切回“不及格”时同样触发事件,所以能正常工作。

1. 同步初始状态与下拉框默认值

把studentGrade的初始状态设为第一个成绩的key("2"),同时将下拉框的defaultValue改为"2",确保弹窗打开时默认选中“不及格”且状态已有值:

// 修改初始状态
const [studentGrade, setGrade] = useState("2");

// 修改下拉框组件
<Form.Control
  name='grade' 
  as="select" 
  defaultValue="2"
  onChange={(event) => handleGradeChange(event.target.value)}>
  {/* 选项渲染逻辑不变 */}
</Form.Control>

2. 弹窗打开时重置成绩状态

在打开弹窗的函数里重置成绩为默认值,避免上次选择的成绩残留影响新的添加操作:

const setOpenModal = (value, names) => {
  openModal(value);
  setStudentNames(names);
  setGrade("2"); // 每次打开弹窗都重置为默认的不及格
};

3. 修复状态异步更新的依赖问题

assignGradeValueToStudent函数里原本使用studentGrade状态,但setGrade是异步操作,可能导致拿到旧值,建议直接用函数传入的grade参数:

const assignGradeValueToStudent = (grade) => {
  var currentStudent = tableData.filter(student => student.names === studentNames)[0];
  if(isEmpty(currentStudent.firstSemester)) {
    currentStudent.firstSemester = currentStudent.firstSemester + grade;
  } else if(currentStudent.firstSemester.substring(currentStudent.firstSemester.length-1) === grade) {
    currentStudent.firstSemester = currentStudent.firstSemester.substring(0, currentStudent.firstSemester.length-1);
    if(isEmpty(currentStudent.firstSemester)) {
      currentStudent.firstSemester = currentStudent.firstSemester + grade;
    } else {
      currentStudent.firstSemester = currentStudent.firstSemester + " " + grade;
    }
  } else {
    currentStudent.firstSemester = currentStudent.firstSemester + " " + grade;
  }
};

4. 可选:添加提交前校验

在saveGrade函数里增加成绩值校验,避免无值提交的情况:

const saveGrade = (value) => {
  if (!studentGrade) {
    alert("请选择成绩");
    return;
  }
  // 原保存逻辑不变
};

内容的提问来源于stack exchange,提问作者FireAndBlood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:57:19