37

I'm using a react hook component with antd. When setting up columns for a table, the render function is giving me an ESLint error:

ESLint: Component definition is missing displayName (react/display-name)

I've tried adding displayName to the object but this doesn't work.

This is how the error looks: enter image description here

This is the code:

const columns_payment_summary_table = [ 
    {
      title: FooConstants.LABEL_QUANTITY_SELECTED,
      dataIndex: 'group',
      key: 'group',
      render: text => (
        <span>{getCountForCountry(text)}</span>
      ),
    }
  ]

Can anyone help?

Here is full component code (well just the relevant bits)

import * as FooConstants from './constants'
import {connect} from 'react-redux'
import React, {useState, useEffect} from 'react'
import {Card, Table} from 'antd'
import PropTypes from 'prop-types'

const propTypes = {
  foos: PropTypes.object.isRequired,
}

function Foos(props) {

  const [selectedFooRows, setSelectedFooRows] = useState([])

  useEffect(() => {
    getFooDetails()
  }, [])

  function getFooDetails() {
    props.dispatch({
      type: FooConstants.GET_FOO_PAYMENT_SUMMARIES,
      params: {
        'group_by': 'country_code',
        'type': FooConstants.CLAIM_FOO,
      }
    })
    props.dispatch({
      type: FooConstants.GET_FOO_PAYMENTS,
      params: {'type': FooConstants.CLAIM_FOO, }
    })
  }

  const columns_payment_summary_table = [
    {
      title: FooConstants.LABEL_QUANTITY_SELECTED,
      dataIndex: 'group',
      key: 'group',
      render: text => (
        <span>{getCountForCountry(text)}</span>
      ),
    }
  ]

  function getCountForCountry(country_code){
    let selected_country = selectedFooRows.filter(function(row){
      return row.group === country_code
    })

    if(selected_country && selected_country.length > 0){
      return selected_country[0].ids.length
    } else {
      return 0
    }
  }

  return (
    <div>
      <Card
        title={FooConstants.LABEL_FOO_SUMMARY}>
        <Table
          columns={columns_payment_summary_table}
          bordered={true}
          dataSource={props.foos.foo_payment_summaries}
          loading={props.foos.foo_payment_summaries_pending && !props.foos.foo_payment_summaries}
          rowKey={record => record.group}
        />
      </Card>
    </div>
  )
}

Foos.propTypes = propTypes

const mapStateToProps = (state) => {
  return {foos: state.foosReducer}
}

export default connect(
  mapStateToProps,
)(Foos)
Leo Farmer
  • 7,730
  • 5
  • 31
  • 47
  • did you look at this https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md? can you post your component code? – duc mai Apr 10 '19 at 20:22
  • @duc-mai Yes, but I don't see the solution to my issue there. I've tried adding displayName to the object, but that doesn't fix the issue. I can see the issue is caused by the render method of the antd column, but I can't work out how to fix it. – Leo Farmer Apr 10 '19 at 20:32

6 Answers6

56

ESLint thinks you are defining a new component without setting any name to it.

This is explained because ESLint cannot recognize the render prop pattern because you are not directly writing this render prop into a component, but into an object.

You can either put the render prop directly into your jsx implementation of the <Column> component,

 const columns_payment_summary_table_render = text => (<span>{getCountForCountry(text)}</span>);
 const columns_payment_summary_table = [{
    title: SettlementConstants.LABEL_QUANTITY_SELECTED, 
    dataIndex: "group", 
    key: "group",        
    // eslint-disable-next-line react/display-name        
    render: columns_payment_summary_table_render
 }];

or shut down the ESLint's error by doing this :

const columns_payment_summary_table = [ 
    {
        title: SettlementConstants.LABEL_QUANTITY_SELECTED,
        dataIndex: 'group',
        key: 'group',
        // eslint-disable-next-line react/display-name
        render: text => (
            <span>{getCountForCountry(text)}</span>
        ),
    }
]

I hope it helped ;)

serv-inc
  • 35,772
  • 9
  • 166
  • 188
Loïc Goyet
  • 720
  • 6
  • 6
  • 7
    I already know how to shut down eslint errors ;-) Please can you expand on the "You can either put the render prop directly into your jsx implementation of the component" part of your answer. – Leo Farmer Apr 10 '19 at 20:38
  • 1
    Just set the function defined as value of the `render` key into its own variable and it should be good. – Loïc Goyet Apr 10 '19 at 20:40
  • 1
    ```js const columns_payment_summary_table_render = text => ( {getCountForCountry(text)} ) const columns_payment_summary_table = [ { title: SettlementConstants.LABEL_QUANTITY_SELECTED, dataIndex: 'group', key: 'group', // eslint-disable-next-line react/display-name render: columns_payment_summary_table_render, } ] ``` – Loïc Goyet Apr 10 '19 at 20:41
  • 1
    That did help! Thank you very much. – Leo Farmer Apr 10 '19 at 20:46
  • Came across this issue https://github.com/yannickcr/eslint-plugin-react/issues/2404 if someone wants to track a permanent solution – lony May 01 '20 at 06:51
38

If anyone needs to avoid this in all the files, add below to the rules section of .eslintrc.js file,

{
  ...
  "rules": {
    "react/display-name": "off"
  }
}
Arosha
  • 1,311
  • 2
  • 16
  • 22
28

Using a normal function for the render key will also remove the ESLint warning without any need for disabling the warning.

const columns_payment_summary_table = [ 
    {
        title: SettlementConstants.LABEL_QUANTITY_SELECTED,
        dataIndex: 'group',
        key: 'group',
        render: function countForCountry(text) {
            return <span>{getCountForCountry(text)}</span>
        },
    }
]
kagundajm
  • 1,152
  • 1
  • 15
  • 26
  • I tried this in a different context, where my code is a method of a non-React class (does not extend Component). Firstly I wrote `renderX = ( x ) =>

    { x }

    ` and got error. After seeing this a added the missing name `renderX = function renderX( x ){

    { x }

    }` The first version is an anonymous function assigned to an object member. The second one is a named function assigned to the same member.
    – Juan Lanus Jan 22 '20 at 16:54
7

Sometimes we can bypass rules if we have an error in only one or two places. What if we have the same use case in multiple places. Each time We have to disable rules.

Instead, we can bypass this error by assigning function to render property.

const getMyHTML = (text) => <span>{getCountForCountry(text)}</span>

const columns_payment_summary_table = [
  {
    title: SettlementConstants.LABEL_QUANTITY_SELECTED,
    dataIndex: 'group',
    key: 'group',
    render: getMyHTML,
  }
]
avatar
  • 161
  • 1
  • 6
1

Using anonymous functions and arrow functions will keep ESLint: Component definition is missing displayName (react/display-name) coming out, I guess this is because that when we are rendering a component through a function, we are giving them a displayName by naming the render function as well.

But using the normal function isn't enough, you might still meet the following warning:

Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.

You have to execute the normal function just right after render it. I passed the two rules by using the following code.

render: () => {
    return (function Actions() {
        return (
            <Button>
            View
            </Button>
                );
            })();
        },
1

This is covered pretty thoroughly in this ESLint issue.

As Loïc suggested, suppressing the lint error is the simplest option here.

However, the lint error exists for a reason -- displayName can be helpful for debugging, particularly in React DevTools' Component view. The easiest way to assign your function a displayName is to use a named function declaration, and hoist the definition:

function renderTable(text) {
  return (<span>{getCountForCountry(text)}</span>);
}
const columns_payment_summary_table = [
  {
    title: SettlementConstants.LABEL_QUANTITY_SELECTED,
    dataIndex: 'group',
    key: 'group',
    render: text => (
      <span>{getCountForCountry(text)}</span>
    ),
  }
]

That's obviously more verbose, though, and if you don't anticipate needing to find the rendered component by name in DevTools, it's simplest to just suppress the error.

ericsoco
  • 24,913
  • 29
  • 97
  • 127