如何将此React钩子组件转换为功能组件

时间:2020-10-28 06:47:13

标签: javascript reactjs react-native

下面是我想转换为钩子的代码-

  const App = () => {

  const [visible, setVisible] = React.useState(false);

  const openMenu = () => setVisible(true);
  const closeMenu = () => setVisible(false);
  const [barClicked, setbarClicked] = React.useState(false);
  const [lineClicked, setlineClicked] = React.useState(false);
  const [pieClicked, setpieClicked] = React.useState(false);

  const BarCharts = () => {
    const fill = 'rgb(134, 65, 244)'
    const data = [50, 10, 40, 95, -4, -24, null, 85, undefined, 0, 35, 53, -53, 24, 50, -20, -80]
    return (
      <View style={styles.sectionContainer}>
        <BarChart style={{ height: 200 }} data={data} svg={{ fill }} contentInset={{ top: 30, bottom: 30 }}>
          <Grid />
        </BarChart>
      </View>
    );
  };

  const LineCharts: () => React$Node = () => {
    const data = [50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]
    return (
          <View style={styles.sectionContainer}>
            <LineChart
                style={{ height: 200 }}
                data={data}
                svg={{ stroke: 'rgb(134, 65, 244)' }}
                contentInset={{ top: 20, bottom: 20 }}
            >
                <Grid />
            </LineChart>
          </View>
    );
  };

  const PieCharts: () => React$Node = () => {
    const data = [50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]
    const randomColor = () => ('#' + ((Math.random() * 0xffffff) << 0).toString(16) + '000000').slice(0, 7)
    const pieData = data
            .filter((value) => value > 0)
            .map((value, index) => ({
                value,
                svg: {
                    fill: randomColor(),
                    onPress: () => console.log('press', index),
                },
                key: `pie-${index}`,
            }))
    return (
          <PieChart style={{ height: 200 }} data={pieData} />
    );
  };

  return (
    <Provider>
      <View
        style={{
          paddingTop: 50,
          flexDirection: 'row',
          justifyContent: 'center',
        }}>
          <Menu
            visible={visible}
            onDismiss={closeMenu}
            anchor={<Button onPress={openMenu}>Show menu</Button>}>
            <Menu.Item onPress={() => setbarClicked(!barClicked)} title="Item 1" />
            <Menu.Item onPress={() => setlineClicked(!lineClicked)} title="Item 2" />
            <Menu.Item onPress={() => setpieClicked(!pieClicked)} title="Item 3" />
          </Menu>
        </View>
        <View>
          <Button onPress={() => setbarClicked(!barClicked)}></Button>
          {barClicked && <BarCharts />}
          <Button onPress={() => setlineClicked(!lineClicked)}></Button>
          {lineClicked && <LineCharts />}
          <Button onPress={() => setpieClicked(!pieClicked)}></Button>
          {pieClicked && <PieCharts />}
       </View>
       <View style={styles.container}>
       </View>
    </Provider>
  );
};

export default App; 

这是通过单击“显示菜单”>第1项进行的操作。enter image description here我自己尝试执行此操作,但返回错误。 -“找不到变量barClicked”。以下是我的想法

  export default class MyComponent extends React.Component {

  state = {
    visible: false,
    barClicked: false,
    lineClicked: false,
    pieClicked: false
  };

  _openMenu = () => this.setState({ visible: true });

  _closeMenu = () => this.setState({ visible: false });

  _setbarClicked = () => this.setState({ barClicked: true });

  _setlineClicked = () => this.setState({ barClicked: true });

  _setpieClicked = () => this.setState({ barClicked: true });


  render() {
    return (
      <Provider>
        <View
          style={{
            paddingTop: 50,
            flexDirection: 'row',
            justifyContent: 'center'
          }}>
          <Menu
            visible={this.state.visible}
            onDismiss={this._closeMenu}
            anchor={
            <Button onPress={this._openMenu}>Show menu</Button>}>
            <Menu.Item onPress={() => this._setbarClicked(!barClicked)} title="Item 1" />
            <Menu.Item onPress={() => this._setlineClicked(!lineClicked)} title="Item 2" />
            <Menu.Item onPress={() => this._setpieClicked(!pieClicked)} title="Item 3" />
          </Menu>
        </View>
        <View>
          <Button onPress={() => this._setbarClicked(!barClicked)}></Button>
          {this.barClicked && <BarCharts />}
          <Button onPress={() => this._setlineClicked(!lineClicked)}></Button>
          {this.lineClicked && <LineCharts />}
          <Button onPress={() => this._setpieClicked(!pieClicked)}></Button>
          {this.pieClicked && <PieCharts />}
       </View>
      </Provider>
    );
  }
} 

我使用了BarChart库中的LineChartPieChartreact-native-svg-chart

2 个答案:

答案 0 :(得分:1)

问题

您没有正确引用任何状态变量,并且处理程序不使用任何参数。您所有的处理程序也会错误地引用您的barClicked状态。

_setbarClicked = () => this.setState({ barClicked: true });

_setlineClicked = () => this.setState({ barClicked: true });

_setpieClicked = () => this.setState({ barClicked: true });

解决方案

如果您希望处理程序采用参数,请按以下方式调整实现:

_setbarClicked = (barClicked) => this.setState({ barClicked });

_setlineClicked = (lineClicked) => this.setState({ lineClicked });

_setpieClicked = (pieClicked) => this.setState({ pieClicked });

并调整回调以正确引用状态,即this.state. barClicked

render() {
  const { barClicked, lineClicked, pieClicked } = this.state;

  return (
    ...

    <Menu.Item onPress={() => this._setbarClicked(!barClicked)} title="Item 1" />
    <Menu.Item onPress={() => this._setlineClicked(!lineClicked)} title="Item 2" />
    <Menu.Item onPress={() => this._setpieClicked(!pieClicked)} title="Item 3" />

    ...

    <Button onPress={() => this._setbarClicked(!barClicked)}></Button>
    {barClicked && <BarCharts />}
    <Button onPress={() => this._setlineClicked(!lineClicked)}></Button>
    {lineClicked && <LineCharts />}
    <Button onPress={() => this._setpieClicked(!pieClicked)}></Button>
    {pieClicked && <PieCharts />}

    ...
  );
}

建议

由于您实际上只是在切换这些状态值,因此只需在处理程序中执行即可。

_setbarClicked = () => this.setState(prevState => ({ !prevState.barClicked }));

_setlineClicked = () => this.setState(prevState => ({ !prevState.lineClicked }));

_setpieClicked = () => this.setState(prevState => ({ !prevState.pieClicked }));

然后将其附加为非匿名回调。

render() {
  const { barClicked, lineClicked, pieClicked } = this.state;

  return (
    ...

    <Menu.Item onPress={this._setbarClicked} title="Item 1" />
    <Menu.Item onPress={this._setlineClicked} title="Item 2" />
    <Menu.Item onPress={this._setpieClicked} title="Item 3" />

    ...

    <Button onPress={this._setbarClicked}></Button>
    {barClicked && <BarCharts />}
    <Button onPress={this._setlineClicked}></Button>
    {lineClicked && <LineCharts />}
    <Button onPress={this._setpieClicked}></Button>
    {pieClicked && <PieCharts />}

    ...
  );
}

答案 1 :(得分:0)

您需要将状态对象放置在类组件的构造函数中(最好是)。

export default class MyComponent extends React.Component {

  constructor(props) {
     super(props)
     this.state = {
        visible: false,
        barClicked: false,
        lineClicked: false,
        pieClicked: false
     };
  }

  ...

并将您的通话从this._setbarClicked(!barClicked)更改为this._setbarClicked(!this.state.barClicked)