nisma pokharel
nisma pokharel

Reputation: 39

convert react class-based to functional component

I am new to learning react and I am having a tough time converting class components into functional components for understanding problems and analyzing . I want to use functional approach for understanding states and life cycle methods how that works in hooks concept .

How we can achieve this?

my code in class are

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
  

    flag: false,
      fields: [],
      Namefield: { value: '', error: '' },
      Emailfield: { value: '', error: '' },
      Mobilefield: { value: '', error: '' },
      tablerows: []
    };
    this.handleName = this.handleName.bind(this);
    this.handleMobile = this.handleMobile.bind(this);
    this.handleMail = this.handleMail.bind(this);
    this.addRow = this.addRow.bind(this);
  }
  handleName(e) {
    this.setState({
      Namefield: {
        value: e.target.value,
        error: false
      }
    })
  }
  handleMobile(e) {
    this.setState({
      Mobilefield: {
        value: e.target.value,
        error: false
      }
    })
  }
  handleMail(e) {
    this.setState({
      Emailfield: {
        value: e.target.value,
        error: false
      }
    })
  }

  addRow(e) {
    e.preventDefault();
    var newdata = { name: this.state.Namefield.value, mobile: this.state.Mobilefield.value, mail: this.state.Emailfield.value }
    // //take the existing state and concat the new data and set the state again
    this.setState({ tablerows: this.state.tablerows.concat(newdata), flag: true });

    const name1 = this.state.Namefield;
    const mob1 = this.state.Mobilefield;
    const mail1 = this.state.Emailfield;

    if (name1.value !== "") {
      const newName = [...this.state.fields, name1]
      this.setState({
        fields: newName,
        Namefield: {
          value: '',
          error: ''
        }
      })
    }

    if (mob1.value !== "") {
      const newMob = [...this.state.fields, mob1]
      this.setState({
        fields: newMob,
        Mobilefield: {
          value: '',
          error: ''
        }
      })
    }

    if (mail1.value !== "") {
      const newMail = [...this.state.fields, mail1]
      this.setState({
        fields: newMail,
        Emailfield: {
          value: '',
          error: ''
        }
      })
    }

  }

  deleteRow(passedID) {
    let tablerows = [...this.state.tablerows]
    tablerows.splice(passedID, 1)
    this.setState({
      tablerows: tablerows
    })
  }

  editRow = (index, type, values) => {

    const newState = this.state.tablerows.map((item, i) => {
      if (i === index) {
        return { ...item, [type]: values };
      }
      return item;
    });
    this.setState({
      tablerows: newState
    });

  }

  render() {

    return (
      <div className="App">
        <header className="App-header">Sample CRUD Operations</header>
        <form >
          <input
            type="text"
            placeholder="Name"
            value={this.state.Namefield.value}
            onChange={this.handleName} />       <br />
          <input
            type="number"
            placeholder="Mobile"
            maxLength="10"
            value={this.state.Mobilefield.value}
            onChange={this.handleMobile} />          <br />
          <input
            type="email"
            placeholder="Email"
            value={this.state.Emailfield.value}
            onChange={this.handleMail} />          <br />
          <div>
            <button onClick={this.addRow}>ADD</button>
          </div>
        </form>

        {this.state.tablerows.length > 0 ?
          <table style={{ "backgroundColor": "rgb(192, 217, 236)" }}>
            <thead style={{ "backgroundColor": "rgb(73, 116, 201)", "color": "white" }}>
              <tr style={{ "height": "50px" }}>
                <th>Name</th>
                <th>Mobile</th>
                <th>Email</th>
                <th>Delete</th>
              </tr>
            </thead>
            <tbody>
              {this.state.tablerows.map((row, index) =>
                <tr key={index}>
                  <td> <input
                    type="text"
                    value={row.name}
                    onChange={(e) => this.editRow(index, "name", e.target.value)} /></td>
                  <td> <input
                    type="number"
                    maxLength="10"
                    value={row.mobile}
                    onChange={(e) => this.editRow(index, "mobile", e.target.value)} /></td>
                  <td> <input
                    type="email"
                    value={row.mail}
                    onChange={(e) => this.editRow(index, "mail", e.target.value)} /></td>
                  <td><button className="deleteBtn" onClick={() => this.deleteRow(index)}>-</button></td>
                </tr>)}
            </tbody>
          </table> : ""}
      </div>
    );
  }}

Upvotes: 3

Views: 19294

Answers (1)

Khabir
Khabir

Reputation: 5854

You can follow the below code and continue rest of your code conversion.

import React from 'react';

function App() {

const [state, setState] = useState({
    flag: false,
    fields: [],
    Namefield: { value: '', error: '' },
    Emailfield: { value: '', error: '' },
    Mobilefield: { value: '', error: '' },
    tablerows: []
  });

const addRow = (e) => {
        e.preventDefault();
        var newdata = { name: state.Namefield.value, mobile: state.Mobilefield.value, mail: state.Emailfield.value };
        //take the existing state and concat the new data and set the state again
        setState({ tablerows: state.tablerows.concat(newdata), flag: true });

    const name1 = state.Namefield;
    const mob1 = state.Mobilefield;
    const mail1 = state.Emailfield;

    if (name1.value !== "") {
        const newName = [...state.fields, name1];
        setState({
            fields: newName,
            Namefield: {
                value: '',
                error: ''
            }
        });
    }

    if (mob1.value !== "") {
        const newMob = [...state.fields, mob1];
        setState({
            fields: newMob,
            Mobilefield: {
                value: '',
                error: ''
            }
        });
    }

    if (mail1.value !== "") {
        const newMail = [state.fields, mail1];
        setState({
            fields: newMail,
            Emailfield: {
                value: '',
                error: ''
            }
        });
    }
}

  const handleName = (e) => {
      setState({
      ...state,
      Namefield: {
        value: e.target.value,
        error: false
      }
    })
  };

  return (
    <div className="App">
      ....
    </div>
  );
};

export default App;

Here are the steps:

  1. use function instead of class
  2. remove the constructor
  3. remove the render() method, keep the return
  4. add const before all methods
  5. remove this.state throughout the component
  6. remove all references to ‘this’ throughout the component
  7. Set initial state with useState()
  8. change this.setState() … instead, call the function that you named in the previous step to update the state…
  9. replace compentDidMount with useEffect
  10. replace componentDidUpdate with useEffect

More detail

Upvotes: 13

Related Questions