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

React路由切换后子组件状态未更新,输入值缓存问题求助

解决React路由切换时输入框值缓存问题

问题场景

我用同一个TestSection组件处理/test/new和/test/edit/:id两个路由,目的是避免代码重复。但从/test/edit/:id路由点击按钮执行history.push("/test/new")跳转后,输入框里的值会被缓存,无法自动清空。

路由配置

<Route exact path={`/test/edit/:id`} component={TestSection}></Route>
<Route exact path={`/test/new`} component={TestSection}></Route>

父组件代码(简化版)

import React, { useEffect, useState } from "react";
import { useHistory, useParams } from "react-router";
import { UseGet, UseWeb } from "../../hooks/http";
import TestInput from "./TestInput";
import Preloader from "../../components/preloader/Preloader";

const TestSection = (props) => {
  const { id } = useParams();
  const history = useHistory();
  const [errors, setErrors] = useState();
  const [category, setCategory] = useState();
  const [IsLoading, setIsLoading] = useState(true);

  const fetchCategory = async (id) => {
    const response = await UseGet(UseWeb("/categories/get"),
      { data: { term: "_id", value: id } }
    );
    setCategory(response.outputData[0])
    setIsLoading(false)
  };

  const handleNew = () => {
    setCategory(undefined)
    history.push('/test/new')
  };

  useEffect(() => {
    if (id) {
      fetchCategory(id).then((category) => {
        setCategory(category);
      });
    } else {
      setIsLoading(false);
    }
  }, []);

  return (
    <div className="container" style={{ maxWidth: "600px", padding: "90px" }}>
      <Preloader loading={IsLoading} />
      {!IsLoading && <React.Fragment>
        <TestInput
          label="Title"
          name="title"
          value={category?.title}
          error={errors?.title}
        />
        <button className="btn btn-primary" onClick={handleNew}>Add new</button>
      </React.Fragment>
      }
    </div>
  );
};

export default TestSection;

子组件代码(简化版)

import React, { useEffect, useState } from "react";
import { FormGroup, Label } from "reactstrap";

const TestInput = (props) => {
  const { value, name, error, copy, size, className, label, counter, onChange, ...rest } = props;
  const [inputValue, setInputValue] = useState(value);

  const handleChange = (ev) => {
    setInputValue(typeof onChange === "function" ? onChange(ev) : ev.target.value)
  };

  console.log(value)

  useEffect(() => {

  }, [])

  return (
    <FormGroup className="mb-2">
      {label && <Label className="form-label fs-13px" htmlFor={name}>
        {label}
        {error && <span className="field-error">{error}</span>}
      </Label>}
      <div className={`form-control-wrap`}>
        <input
          type="text" id={name} value={inputValue} name={name}
          className={`form-control form-control-${size ? size : "sm"} ${className}`}
          onChange={handleChange}
          {...rest}
        />
      </div>
    </FormGroup>
  );
};

export default TestInput;

解决方案

1. 父组件监听路由参数变化,重置状态

原代码中useEffect的依赖为空数组,仅在组件首次挂载时执行。当路由从/test/edit/:id切换到/test/new时,组件不会重新挂载,useEffect不会触发,导致category状态没有被重置。

修改父组件的useEffect,将id加入依赖数组,同时清理冗余的setCategory调用:

useEffect(() => {
  if (id) {
    setIsLoading(true);
    fetchCategory(id);
  } else {
    setCategory(undefined); // 清空category,让输入框值重置
    setIsLoading(false);
  }
}, [id]); // 监听id变化,路由切换时自动执行

同时修改fetchCategory里的冗余代码(原代码中fetchCategory已经调用了setCategory,不需要在then里重复设置):

const fetchCategory = async (id) => {
  const response = await UseGet(UseWeb("/categories/get"),
    { data: { term: "_id", value: id } }
  );
  setCategory(response.outputData[0]);
  setIsLoading(false);
};

2. 子组件同步props的value变化

子组件中用useState初始化了inputValue,但后续props.value变化时(比如父组件category变为undefined),inputValue没有同步更新,导致输入框显示旧值。

给子组件添加useEffect监听props.value,同步更新inputValue:

useEffect(() => {
  setInputValue(value);
}, [value]); // 当props的value变化时,更新输入框的值

3. 优化跳转逻辑(可选)

原handleNew中先设置category再跳转,由于React状态更新是异步的,可能出现跳转后状态还未更新的情况。现在依赖useEffect监听id变化来重置状态,所以可以简化handleNew:

const handleNew = () => {
  history.push('/test/new');
};

完成以上修改后,从/test/edit/:id跳转到/test/new时,输入框的值会自动清空,不再缓存旧内容。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:44:58