Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop input from re-rendering onChange

I am capturing the input value as a state and on button submit I want to add the result into an array.

The problem I am having is every time I type in a character in the input field it creates a new array before I even hit the submit button.

Following is the screenshot of the weird behaviour.

enter image description here

Here is my code:

import React, { Component } from "react";
import autoBind from "react-autobind";

let fixtures = [];

const submitFixture = (homeTeam, awayTeam) => {
  fixtures.push({
    homeTeam: homeTeam,
    awayTeam: awayTeam
  });
};
class CreateFixture extends Component {
  constructor(props) {
    super(props);
    autoBind(this);

    this.state = {
      homeTeam: "",
      awayTeam: ""
    };
  }

  render() {
    const { homeTeam, awayTeam } = this.state;

return (
  <React.Fragment>
    <p>Home Team</p>
    <input
      value={homeTeam}
      onChange={e => {
        this.setState({ homeTeam: e.target.value });
      }}
    />
    <p>Away Team</p>
    <input
      value={awayTeam}
      onChange={e => {
        this.setState({ awayTeam: e.target.value });
      }}
    />
    <button onClick={submitFixture(homeTeam, awayTeam)}>
      Create fixture
    </button>
    {console.log(fixtures)}
  </React.Fragment>
);
  }
}

export default CreateFixture;
like image 658
coding1223322 Avatar asked Mar 06 '23 01:03

coding1223322


1 Answers

You are invoking your submitFixture function directly on render by writing onClick={submitFixture(homeTeam, awayTeam)}. This way you will add a new element to the array every time the component is re-rendered.

You could create a new inlined function that calls submitFixture when the click event occurs instead.

<button onClick={() => submitFixture(homeTeam, awayTeam)}>

If you want to render fixtures in some way, it's better to put them in the component state instead.

Example

class CreateFixture extends React.Component {
  state = {
    homeTeam: "",
    awayTeam: "",
    fixtures: []
  };

  submitFixture = () => {
    this.setState(({ homeTeam, awayTeam, fixtures }) => ({
      fixtures: [...fixtures, { homeTeam, awayTeam }]
    }));
  };

  render() {
    const { homeTeam, awayTeam, fixtures } = this.state;

    return (
      <div>
        <p>Home Team</p>
        <input
          value={homeTeam}
          onChange={e => {
            this.setState({ homeTeam: e.target.value });
          }}
        />
        <p>Away Team</p>
        <input
          value={awayTeam}
          onChange={e => {
            this.setState({ awayTeam: e.target.value });
          }}
        />
        <button onClick={this.submitFixture}>Create fixture</button>
        <div>{JSON.stringify(fixtures)}</div>
      </div>
    );
  }
}

ReactDOM.render(<CreateFixture />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>
like image 187
Tholle Avatar answered Mar 15 '23 17:03

Tholle