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

React类组件转Hooks后切换nextPackage可见性按钮失效如何解决

问题根因

你遇到的问题确实是状态对象处理错误导致,核心存在两处错误:

  • handleShowNextPackageDetails方法直接将整个状态对象替换为布尔值:你定义的initialState是包含多个业务属性的对象,直接执行setInitialState(!showNextPackage)会把状态整体改成true/false,原有pricelist、nextPackage、showNextPackage等属性全部丢失,自然无法控制折叠面板的展示。
  • 未注意useState更新逻辑和类组件setState的差异:类组件的setState会自动做状态的浅层合并,但useState的更新函数是直接替换整个状态,你在useEffect中调用setInitialState时仅传入了三个属性,会直接把初始状态中定义的showNextPackage属性清除,状态结构从初始化阶段就已经不符合预期。

修复方案

方案1:保持单状态对象的修复方式

如果不想调整原有状态结构,只需要修正两处状态更新的逻辑,更新时保留原有状态的其他属性即可:

  1. 修正handleShowNextPackageDetails方法:
const handleShowNextPackageDetails = () => {
  setInitialState(prevState => ({
    ...prevState,
    showNextPackage: !prevState.showNextPackage
  }));
};
  1. 修正useEffect中的状态更新逻辑:
useEffect(() => {
  const { getData } = props;
  getData(
    'price-lists/profile',
    { defaultSort, resourceArrayName: 'pricelist' },
    true
  ).then((res) => {
    setInitialState(prevState => ({
      ...prevState,
      pricelist: res.data._embedded.pricelist[0],
      nextPackage: res.data._embedded.pricelist[1],
      loading: false,
    }));
  });
// 建议将getData加入依赖数组,避免闭包问题
}, [getData]);

方案2:更合理的拆分状态方案(推荐)

对于关联性较弱的状态,拆分为多个独立的useState管理是更符合Hooks设计理念的实现,后续维护和更新不需要额外处理对象合并,出错概率更低:

const Pricing = props => {
  const [loading, setLoading] = useState(true);
  const [pricelist, setPricelist] = useState({
    pricelistEntries: [],
    name: '',
    monthlySubscriptionFee: '',
    currency: '',
    validFrom: '',
    smsInPackage: '',
  });
  const [nextPackage, setNextPackage] = useState(undefined);
  const [showNextPackage, setShowNextPackage] = useState(false);

  useEffect(() => {
    const { getData } = props;
    getData(
      'price-lists/profile',
      { defaultSort, resourceArrayName: 'pricelist' },
      true
    ).then((res) => {
      setPricelist(res.data._embedded.pricelist[0]);
      setNextPackage(res.data._embedded.pricelist[1]);
      setLoading(false);
    });
  }, [getData]);

  const handleShowNextPackageDetails = () => {
    setShowNextPackage(prev => !prev);
  };

  const { classes } = props;
  return (
    <React.Fragment>
      <Paper className={classes.root}>
        <Loading loading={loading} spinner>
          <React.Fragment>
            <Typography variant="body1" style={{ marginBottom: 10 }}>
              <FormattedMessage id="administration.packages.form.section.package.info" />
            </Typography>
            <PackageView pricelist={pricelist} />
          </React.Fragment>
        </Loading>
      </Paper>
      {nextPackage && (
        <Paper className={classes.next}>
          <div style={{ display: 'flex' }}>
            <Typography variant="body1" style={{ flexGrow: 1 }}>
              <FormattedMessage id="account.packages.form.section.next.package" />
            </Typography>
            <Button
              color="secondary"
              onClick={handleShowNextPackageDetails}
              size="small"
              style={{ marginBottom: '5px' }}
            >
              <FormattedMessage id="account.balance.details.label" />
              <ExpandMoreIcon
                className={classnames(classes.expand, {
                  [classes.expandOpen]: showNextPackage,
                })}
              />
            </Button>
          </div>
          <Collapse in={showNextPackage} timeout="auto" unmountOnExit>
            <PackageView pricelist={nextPackage} />
          </Collapse>
        </Paper>
      )}
    </React.Fragment>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 10:39:03