Raushan Singh
Raushan Singh

Reputation: 105

How to convert class based component into function based component?

Right now I have a class-based component but I want to convert my component into function-based. The code is below here. I have select all checkbox written in a class-based component. but now I want to convert that component into function-based, I have changed all the methods and props into my code but there is some error of state. I am not getting a possible error.

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Checkbox } from 'antd';

const CheckboxGroup = Checkbox.Group;

const plainOptions = ['Apple', 'Pear', 'Orange'];
const defaultCheckedList = ['Apple', 'Orange'];

class App extends React.Component {
  state = {
    checkedList: defaultCheckedList,
    indeterminate: true,
    checkAll: false,
  };

  onChange = checkedList => {
    this.setState({
      checkedList,
      indeterminate: !!checkedList.length && checkedList.length < plainOptions.length,
      checkAll: checkedList.length === plainOptions.length,
    });
  };

  onCheckAllChange = e => {
    this.setState({
      checkedList: e.target.checked ? plainOptions : [],
      indeterminate: false,
      checkAll: e.target.checked,
    });
  };

  render() {
    return (
      <div>
        <div className="site-checkbox-all-wrapper">
          <Checkbox
            indeterminate={this.state.indeterminate}
            onChange={this.onCheckAllChange}
            checked={this.state.checkAll}
          >
            Check all
          </Checkbox>
        </div>
        <br />
        <CheckboxGroup
          options={plainOptions}
          value={this.state.checkedList}
          onChange={this.onChange}
        />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('container'));

now I am converting my component into function-based. but having an issue. Can anybody suggest me the possible mistake, please ... the checkbox is showing all options but unable to check the box or cant check all options at once. Can anybody suggest me some answer so I can solve my issue?

import React, {useState} from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Checkbox } from 'antd';

const CheckboxGroup = Checkbox.Group;

const plainOptions = ['Apple', 'Pear', 'Orange'];
const defaultCheckedList = ['Apple', 'Orange'];

function App (props) {
  state = {
    checkedList: defaultCheckedList,
    indeterminate: true,
    checkAll: false,
  };

  const onChange = checkedList => {
    this.setState({
      checkedList,
      indeterminate: !!checkedList.length && checkedList.length < plainOptions.length,
      checkAll: checkedList.length === plainOptions.length,
    });
  };

  const onCheckAllChange = e => {
    this.setState({
      checkedList: e.target.checked ? plainOptions : [],
      indeterminate: false,
      checkAll: e.target.checked,
    });
  };


    return (
      <div>
        <div className="site-checkbox-all-wrapper">
          <Checkbox
            indeterminate={this.state.indeterminate}
            onChange={this.onCheckAllChange}
            checked={this.state.checkAll}
          >
            Check all
          </Checkbox>
        </div>
        <br />
        <CheckboxGroup
          options={plainOptions}
          value={this.state.checkedList}
          onChange={this.onChange}
        />
      </div>
    );

}

ReactDOM.render(<App />, document.getElementById('container'));

Upvotes: 1

Views: 182

Answers (3)

Amir Gorji
Amir Gorji

Reputation: 3335

In class components you simply write a state object ' this.state ' and describe the states in that object, but in functional components things get a little different.

You should use React hooks and you must set every single state separately, with array constants.

If we suppose that the code is completely error/bug free, the code will be like this:

(notice that 'this.' is only used in class components)

import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Checkbox } from 'antd';

const CheckboxGroup = Checkbox.Group;

const plainOptions = ['Apple', 'Pear', 'Orange'];
const defaultCheckedList = ['Apple', 'Orange'];


function App(props) {
  const [checkedList, setCheckedList] = useState(defaultCheckedList);
  const [indeterminate, setIndeterminate] = useState(true);
  const [checkAll, setCheckAll] = useState(false);

  const onChange = event => {
    setCheckedList(event);
    setIndeterminate(!!event.length && event.length < plainOptions.length)
    setCheckAll(event.length === plainOptions.length)
  };

  const onCheckAllChange = e => {
    setCheckedList(e.target.checked ? plainOptions : []);
    setIndeterminate(false);
    setCheckAll(e.target.checked);
  };


  return (
    <div>
      <div className="site-checkbox-all-wrapper">
        <Checkbox
          indeterminate={indeterminate}
          onChange={onCheckAllChange}
          checked={checkAll}
        >
          Check all
              </Checkbox>
      </div>
      <br />
      <CheckboxGroup
        options={plainOptions}
        value={checkedList}
        onChange={onChange}
      />
    </div>
  );

}

ReactDOM.render(<App />, document.getElementById('container'));

The second argument of the array changes the amount of the first argument and then it calls a screen update api.

You can learn more about lifecycles of functional components in React Docs.

Upvotes: 1

HermitCrab
HermitCrab

Reputation: 3274

Replace:

state = {
  checkedList: defaultCheckedList,
  indeterminate: true,
  checkAll: false,
};

with:

const [checkedList, setCheckedList] = React.useState(defaultCheckedList);
const [indeterminate, setIndeterminate] = React.useState(true);
const [checkAll, setCheckAll] = React.useState(false);

To render the state, just use the first item:

<div>{indeterminate}</div>

To change the state, use the second item:

setIndeterminate(false);

Upvotes: 0

Milos N.
Milos N.

Reputation: 4873

In function component, you can't use state on that way !

Before react Hooks, you didn't have the opportunity to have the state's inner function components. Luckily, after 16.8 in react you have React Hooks!

In your case, you must use useState(); hook and your current state put in that hook.

import React, {useState} from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Checkbox } from 'antd';

const CheckboxGroup = Checkbox.Group;

const plainOptions = ['Apple', 'Pear', 'Orange'];
const defaultCheckedList = ['Apple', 'Orange'];

function App (props) {
  const [state, setState] = useState({
    checkedList: defaultCheckedList,
    indeterminate: true,
    checkAll: false,
  });

  const onChange = checkedList => {
    setState({
      checkedList,
      indeterminate: !!checkedList.length && checkedList.length < plainOptions.length,
      checkAll: checkedList.length === plainOptions.length,
    });
  };

  const onCheckAllChange = e => {
    setState({
      checkedList: e.target.checked ? plainOptions : [],
      indeterminate: false,
      checkAll: e.target.checked,
    });
  };


    return (
      <div>
        <div className="site-checkbox-all-wrapper">
          <Checkbox
            indeterminate={state.indeterminate}
            onChange={onCheckAllChange}
            checked={state.checkAll}
          >
            Check all
          </Checkbox>
        </div>
        <br />
        <CheckboxGroup
          options={plainOptions}
          value={state.checkedList}
          onChange={onChange}
        />
      </div>
    );

}

ReactDOM.render(<App />, document.getElementById('container'));

Other this keyword you have only in-class component.

Upvotes: 0

Related Questions