reactjs - React 类组件到 Hooks

标签 reactjs react-hooks

我正在转换这个类组件

class Pricing extends React.Component {
  state = {
    loading: true,
    pricelist: {
      pricelistEntries: [],
      name: '',
      monthlySubscriptionFee: '',
      currency: '',
      validFrom: '',
      smsInPackage: '',
    },
    nextPackage: undefined,
    showNextPackage: false,
  };

  componentDidMount() {
    const { getData } = this.props;
    getData(
      'price-lists/profile',
      { defaultSort, resourceArrayName: 'pricelist' },
      true
    ).then((res) => {
      this.setState({
        pricelist: res.data._embedded.pricelist[0],
        nextPackage: res.data._embedded.pricelist[1],
        loading: false,
      });
    });
  }

  handleShowNextPackageDetails = () => {
    this.setState((state) => ({ showNextPackage: !state.showNextPackage }));
  };

  render() {
    const { classes } = this.props;
    const { pricelist, loading, showNextPackage, nextPackage } = this.state;
    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={this.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>
    );
  }
}

到这个功能组件

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

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

  const handleShowNextPackageDetails = () => {
    setInitialState(!showNextPackage);
  };

    const { classes } = props;
    const { pricelist, loading, showNextPackage, nextPackage } = initialState;
    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>
    );

}

但是,用于更改 nextPackage 可见性的按钮不起作用。在类组件上它工作正常,并且功能不想在单击时扩展内容。可能是对象状态有问题吗? 有没有更好的方法来转换此组件以及如何使 handleShowNextPackageDetails 工作?

最佳答案

当您设置状态时,例如:setInitialState(!showNextPackage);,您也会覆盖其他状态变量。所以对象就变成了: false:

而是在所有 setInitialState 中使用展开运算符,因为它是一个对象:

setInitialState(is => ({...is, nextPackage: !is.nextPackage})

此外,还有一个更新价目表的示例:

const addEntry = priceListEntry => {
  setInitialState(is => ({
     ...is, pricelistEntries: [...is.pricelistEntries, priceListEntry]
  }))
}

说明:

扩展运算符允许您更改所需的字段,而其他字段保持不变。 setInitialState(is 中的 is 只是当前状态。因此,除了要更改的字段之外,您保留当前状态:

let obj = {name: 'Test', value: 10}
console.log(obj)

obj = {...obj, value: 15}
console.log(obj)

obj = {...obj, newValue: 20}
console.log(obj)

关于reactjs - React 类组件到 Hooks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68834380/

相关文章:

reactjs - 第 0 行 : Parsing error: Cannot read property 'map' of undefined

reactjs - react 。当在组件函数中导入函数时,我能知道为什么它不起作用 hooks setState..?

javascript - 如何使用 eslint 在 FormattedMessage 组件中强制描述属性

javascript - ReactJS:来自多个 JSON 文件的下拉搜索结果

javascript - Blockstack App 在 npm install ERR 上失败!配置错误

javascript - 如何在 React Redux 中获取状态的先前值

javascript - 如何在嵌套对象中设置状态

javascript - React 在从 API 调用接收数据后不更新 UI(使用 Hook )

javascript - 是否有从对象渲染组件的方法? - react

svg - 将 SVG 标记添加到 React 组件