React-apollo: Apollo Query and Mutation components: JSX props should not use functions (react/jsx-no-bind)

Created on 2 Jul 2018  路  2Comments  路  Source: apollographql/react-apollo

I'm using the Apollo's <Mutation> component like this:

import gql from "graphql-tag";
import { Mutation } from "react-apollo";

const ADD_TODO = gql`
  mutation addTodo($type: String!) {
    addTodo(type: $type) {
      id
      type
    }
  }
`;

const AddTodo = () => {
  let input;

  return (
    <Mutation mutation={ADD_TODO}>
      {(addTodo, { data }) => (
        <div>
          <form
            onSubmit={e => {
              e.preventDefault();
              addTodo({ variables: { type: input.value } });
              input.value = "";
            }}
          >
            <input
              ref={node => {
                input = node;
              }}
            />
            <button type="submit">Add Todo</button>
          </form>
        </div>
      )}
    </Mutation>
  );
};

I get this error:

[eslint] JSX props should not use functions (react/jsx-no-bind)

I think it is complaining about:

onSubmit={e => {
  e.preventDefault();
  addTodo({ variables: { type: input.value } });
  input.value = "";
}}

because is an arrow function.

But it's the default in Apollo React Docs: https://www.apollographql.com/docs/react/essentials/mutations.html.

I asked eslint-plugin-react team how to proceed, here: https://github.com/yannickcr/eslint-plugin-react/issues/1872

docs has-reproduction

Most helpful comment

@mike-marcacci Where does "addTodo" come from in _onSubmit in your example?

All 2 comments

Hey @johnunclesam, this is an optimization that isn't always necessary, and doesn't really have anything to do with apollo.

Basically you sometimes want to avoid creating new functions/objects in a render method and passing them to child props because this will force that child to re-render. However, depending on the implementation of that child component and where this happens in your app's tree, it often doesn't matter.

Apollo uses a pattern called "render prop function" which makes it really easy to compose. However, the most straightforward way to use it is with an inline function. I would recommend you disable that eslint warning, and optimize when performance becomes a problem. However, if you really want to keep the rule, you can refactor to something like this:

import gql from "graphql-tag";
import { Mutation } from "react-apollo";
import { Component } from "react";

const ADD_TODO = gql`
  mutation addTodo($type: String!) {
    addTodo(type: $type) {
      id
      type
    }
  }
`;

class AddTodo extends Component {
  state = { value: "" };

  _onSubmit = e => {
    e.preventDefault();
    addTodo({ variables: { type: this.state.value } });
    this.setState({
      value: ""
    })
  };

  _onChange = e => {
    this.setState({
      value: e.target.value
    });
  };

  _renderProp = (addTodo, { data }) => (
    <div>
      <form
        onSubmit={this._onSubmit}
      >
        <input
          value={this.state.value}
          onChange={this._onChange}
        />
        <button type="submit">Add Todo</button>
      </form>
    </div>
  );

  render () {
    return (
      <Mutation mutation={ADD_TODO}>
        {this._renderProp}
      </Mutation>
    );
  }
};

@mike-marcacci Where does "addTodo" come from in _onSubmit in your example?

Was this page helpful?
0 / 5 - 0 ratings