Search code examples
reactjscomponentsreact-router-dom

ReactJS: Each child in a list should have a unique "key" prop


What is the best way to fix this type of problem?

I'm trying to use the Link (react-router-dom) for ReactJS a button will redirect to another page "DadosEmpresaPage" to "SelecaoPlaenoElegibilidade", but it gives an error in my ComponentSelector, now it is fixed, I just have to somehow make a "list" to render my components?

enter image description here enter image description here

My index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

// Materialize
import 'materialize-css/dist/css/materialize.min.css';
import 'materialize-css/dist/js/materialize.js';

// Component Dynamic Render Selector
import ComponentSelector from './components/ComponentSelector/ComponentSelector';

const ComponentList = ['NavigationBar', 'Breadcrumbs', 'DadosEmpresaPage'];

ReactDOM.render(
  <React.StrictMode >

    <ComponentSelector Render={ComponentList} />

  </React.StrictMode>,
  document.getElementById('root')
);

My ComponentSelector.js

// React
import React from 'react';

// Componentes
import HomePage from '../../pages/HomePage/HomePage';
import NavigationBar from '../../components/NavigationBar/NavigationBar';
import Breadcrumbs from '../../components/Breadcrumbs/Breadcrumbs';
import DadosEmpresaPage from '../../pages/DadosEmpresaPage/DadosEmpresaPage';
import InformacoesComplementaresPage from '../../pages/InformacoesComplementaresPage/InformacoesComplementaresPage';
import ElegibilidadePage from '../../pages/ElegibilidadePage/ElegibilidadePage';
import SelecaoPlanoElegibilidadePage from '../../pages/SelecaoPlanoElegibilidadePage/SelecaoPlanoElegibilidadePage';
import DistribuicaoFaixasElegibilidadePage from '../../pages/DistribuicaoFaixasElegibilidadePage/DistribuicaoFaixasElegibilidadePage';
import GerarPropostaPage from '../../pages/GerarPropostaPage/GerarPropostaPage';

const componentMapping = {
  HomePage,
  NavigationBar,
  Breadcrumbs,
  DadosEmpresaPage,
  InformacoesComplementaresPage,
  ElegibilidadePage,
  SelecaoPlanoElegibilidadePage,
  DistribuicaoFaixasElegibilidadePage,
  GerarPropostaPage
};

const ComponentRender = ({ Render }) => {
  return (
    <div>
      {Render.map((componentName) => {
        const Component = componentMapping[componentName];
        return <Component />;
      })}
    </div>
  );
};

export default ComponentRender;

My DadosEmpresaPage.js

import React from 'react';
import './DadosEmpresaPage.css';
import StepCounter from '../../components/StepCounter/StepCounter';
import HeaderPage from '../../components/PageHeader/PageHeader'
import { Link } from "react-router-dom";

export default class DadosEmpresaPage extends React.Component {

  state = {

  }


  componentDidMount() {


  }

  render() {
    return (
      <div>
        <div className='row container'>
          <div className='col s9 m9 l9'>
            <br /><b><h5>Nova Oportunidade</h5></b>
          </div>
          <div className='col s3 m3 l3'>
            <br /><StepCounter step='1' total='4' />
          </div>
        </div>
        <div className='row container'>

          <HeaderPage Spotlight='Dados' Title='da Empresa' Description='Para iniciar a nova oportunidade, preencha ao lado os dados cadastrais da empresa, informe a quantidade de pessoas que farão parte do plano, assim como o número de titulares.' />

          <div className='col s5 m5 l5 offset-s3 offset-m3 offset-l3'>

            <div class="input-field col s12">
              <label for="cnpj">CNPJ</label>
              <input id="cnpj" type="text" name="cnpj" onChange={this.onChange} />
            </div>

            <div class="input-field col s12">
              <label for="razaoSocial">Razão Social</label>
              <input id="razaoSocial" type="text" name="razaoSocial" onChange={this.onChange} />
            </div>

            <div class="input-field col s12">
              <label for="estado">Estado</label>
              <input id="estado" type="text" name="estado" onChange={this.onChange} />
            </div>

            <div class="input-field col s12">
              <label for="cidade">Cidade</label>
              <input id="cidade" type="text" name="cidade" onChange={this.onChange} />
            </div>

            <div class="input-field col s12">
              <label for="quantidadeVidas">Quantidade de Vidas</label>
              <input id="quantidadeVidas" type="text" name="quantidadeVidas" onChange={this.onChange} />
            </div>

            <div class="input-field col s12">
              <label for="quantidadeTitulares">Quantidade de Titulares</label>
              <input id="quantidadeTitulares" type="text" name="quantidadeTitulares" onChange={this.onChange} />
            </div>

            <Link  to={{pathname: '/InformacoesComplementaresPage'}}>NavigateNow</Link>
            </div>

          </div>

        </div>
    );
  }
};

Solution

  • While rendering list in React you should give each element a unique key identifier.

    One of the quickest way to solve it is by using index as a key.

    const ComponentRender = ({ Render }) => {
      return (
        <div>
          {Render.map((componentName, index) => {
            const Component = componentMapping[componentName];
            return <Component key={index} />;
          })}
        </div>
      );
    };
    

    But in case you would like to add / remove elements or shuffle order please consider that this exact way (providing indexes as a keys) might not work for you. Then using some other unique and unchangeable values as a keys will solve your issue.