Filtrar una lista con React

Hmm, no veo mi omisión, pero me sale una página en blanco con un error de consola diciendo:

Users.js:9 Uncaught TypeError: Cannot read property 'filter' of undefined
    at Users.render (Users.js:9)

Al parecer I'm utilizando 'filter()' incorrectamente. Miré a mi alrededor, pero didn't encontrar nada 'React' relacionados. ¿Alguien puede ayudar? Aquí están los archivos:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Users from './Users';

ReactDOM.render(
  <Users list={[
    { name: 'Tyler', friend: true },
    { name: 'Ryan', friend: true },
    { name: 'Michael', friend: false },
    { name: 'Mikenzie', friend: false },
    { name: 'Jessica', friend: true },
    { name: 'Dan', friend: false }
    ]}
  />,
  document.getElementById('root')
);

Users.js

import React from 'react';

class Users extends React.Component {
  render() {
    return (
      <div>
        <h1>Friends:</h1>
        <ul>
          {this.props.list.friend.filter(function (friend) {
            return <li>{friend[0] === 'true'}</li>
        })}
        </ul>

        <hr />

        <h1>Non Friends:</h1>
        <ul>
          {this.props.list.friend.filter(function (nonFriend) {
            return <li>{nonFriend[0] === 'false'}</li>
          })}
        </ul>
      </div>
    );
  }
}

export default Users;

Estás llamando a .friend en la propia lista cuando es una propiedad de cada objeto de tu array. También estás usando .filter, pero no creo que lo estés usando correctamente. .filter devolverá un array con ciertos elementos donde la función pasada devuelve un valor verdadero. Así es como podría hacerlo con .filter:

var nonFriends = this.props.list.filter(function (user) {
  return !user.friend;
});

var friends = this.props.list.filter(function (user) {
  return user.friend;
});

return (
  <div>
    <h1>Friends:</h1>
    <ul>{ friends }</ul>
    <h1>Non Friends:</h1>
    <ul>{ nonFriends }</ul>
  </div>
);

También podrías hacer un .forEach para 1 pasada por el array si el array es grande:

var nonFriends = [], friends = [];

this.props.list.forEach(function (user) {
  if (user.friend) {
    friends.push(user);
  } else {
    nonFriends.push(user);
  }
});

// now render friends and nonFriends
Comentarios (0)

Creo que está intentando filtrar el atributo, y no la lista. Trate de cambiar esto:

this.props.list.friend.filter

por esto:

this.props.list.filter
Comentarios (0)

Yo haría algo como esto, que es un poco más sencillo

{this.props.list.map(function (person, i) {
  {return person.friend
    ?(<li key={i}>{person.name}</li>)
    : null
  }
})}
  1. Estás iterando sobre la propia lista, no sobre un elemento de la lista, por eso this.props.list.friend.filter no funcionaba.
  2. Yo usaría map porque en realidad no estás filtrando las listas en este caso. Si quisieras, podrías filtrar la lista de antemano en amigos y no amigos y mapear sobre esos elementos, lo que sería más sencillo de ver para otro ingeniero.
  3. React quiere "claves" en el marcado para los elementos iterados creados. Así es como React crea las relaciones entre los componentes en el árbol de estado.
Comentarios (0)