Quiero escribir iniciales únicas antes de enumerar una serie de nombres, por lo que, dados los nombres constantes = ["Bill", "Jack", "john"], me gustaría imprimir algo como:
<ul> <li>B <ul> <li>Bill</li> </ul> </li> <li>J <ul> <li>John</li> <li>jack</li> </ul> </li> </ul>La forma en que encontré hacer esto es empujar el JSX a una matriz antes de renderizarlo así:
const RenderNames = () => { let initials = []; let renderData = []; names.forEach(name => { let initial = name.charAt(0).toUpperCase(); if(initials.indexOf(initial) === -1){ initials.push(initial) renderData.push(<li>{initial}</li>) } renderData.push(<li>{name}</li>) }); return <ul>{renderData}</ul>; }Pero siento que el código es un poco torpe, y solo puedo insertar etiquetas que se cierran inmediatamente. ¿Es esta la mejor manera de hacer las cosas o podría hacerse mejor?
Aquí vamos:
const names = ['Bill', 'Jack', 'john', 'Alex']; const groupedNames = names.reduce((accumulator, name) => { // first char of name, uppercased const firstLetter = name[0].toUpperCase(); // check if data for key exist const namesList = accumulator[firstLetter] || []; // check if name in array exist to prevent duplicates // keep in mind for example John and john are not the same if (!namesList.includes(name)) { namesList.push(name); } // collect data and return return {...accumulator, [firstLetter]: namesList} }, {});y el resultado es
{ B: [ 'Bill' ], J: [ 'Jack', 'john' ], A: [ 'Alex' ] } Luego puede ordenar las claves y map() sobre él.
Puedes usar esto::
const names = ['Bill', 'John', 'bob', 'Jack']; const category = names.reduce((unique, name) => { const char = name.charAt(0).toUpperCase(); return (unique[char] ? { ...unique, [char]: [...unique[char], name] } : { ...unique, [char]: [name] }); }, {}); return ( <div className="App"> <ul> { Object.entries(category).map(([key, value]) => <ul> <li>{key}</li> { value.length && <ul> { value.map(name => <li>{name}</li> ) } </ul> } </ul> )} </ul> </div> );Revisa este enlace:
https://codesandbox.io/s/vigilant-sound-ukv0q?file=/src/App.js