1
votes

Réagir - Ajouter un utilisateur à la liste des favoris

J'ai une liste d'utilisateurs simple avec plusieurs détails de l'API suivante: https: // gorest .co.in / public-api / users , où je souhaite ajouter un utilisateur sélectionné à une liste de favoris. Je travaille avec react-router pour naviguer entre les pages. Est-ce possible avec React ou ai-je également besoin de Redux?

J'ai un EXEMPLE EN DIRECT ici avec la page utilisateur et les favoris.

Voici le code ci-dessous pour la liste des utilisateurs:

import React from "react";
import axios from "axios";

import NavLinks from "./components/navLink";

export default class UserList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      list: [],
      addToFav: false
    };
    this.list = [];
  }

  componentDidMount() {
    this.getList();
  }

  /* get users list */
  getList = async () => {
    const api =
      "https://gorest.co.in/public-api/users?_format=json&access-token=3qIi1MDfD-GXqOSwEHHLH73Y3UitdaFKyVm_";

    await axios
      .get(api)
      .then(response => {
        this.list = response.data.result;
        this.setState({
          list: this.list
        });
      })
      .catch(err => {
        console.log(err);
      });
  };

  addToFav = () => {
    this.setState(
      {
        addToFav: !this.state.addToFav
      },
      () => console.log(this.state.addToFav)
    );
  };

  render() {
    let style = {
      display: "grid",
      gridTemplateColumns: "repeat(auto-fill, minmax(250px, 1fr))",
      padding: "1rem",
      gridGap: "1rem 1rem"
    };

    return (
      <div>
        <NavLinks />
        <ul style={style}>
          {this.state.list.map(user => {
            return (
              <li key={user.id}>
                <div>
                  <img className="thumb" alt="" src={user._links.avatar.href} />
                </div>

                <div className="userInfo">
                  <p>
                    {user.first_name} {user.last_name}
                  </p>
                </div>
                <button onClick={this.addToFav}>Add to Favorites</button>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}

Merci!


11 commentaires

Vous avez fourni un objectif mais aucun problème ou question spécifique lié à l'atteinte de cet objectif? Quelle est ta question?


Étant donné que la liste des favoris doit être accessible par les deux itinéraires, le moyen le plus simple est de la mettre dans l ' état de votre application principale, puis de la transmettre à l'itinéraire des favoris. Ensuite, vous passez une méthode pour ajouter un favori par ID au composant qui affiche la liste entière.


Si votre application est petite, vous pouvez y parvenir sans utiliser redux, mais si vous avez des exigences plus complexes, il serait préférable d'utiliser react


Oui, utilisez un UsersContext.Provider au-dessus de vos itinéraires. et quand vous en avez besoin, utilisez simplement Contexte ou Consumer Quelle version de réaction vous utilisez?


Mon application est en effet petite. Je n'ai trouvé que des exemples utilisant Redux, c'est pourquoi je pose cette question. Je n'ai pas la moindre idée de le faire uniquement avec React.


J'utilise la dernière version @MohamedELAYADI


Okey, il existe de nombreuses façons de le faire, en utilisant uniquement react. Connaissez-vous les crochets?


Je suis plutôt nouveau avec les crochets, tbh. @MohamedELAYADI


Que voulez-vous dire, "vous n'avez pas la moindre idée"? Ajoutez l'état et la méthode addFav à votre application principale, puis transmettez-les comme accessoires aux enfants, si nécessaire. Où est exactement le problème? Ne voulez pas être impoli, mais simplement curieux de savoir où vous êtes exactement coincé. Au cas où vous vous demandez comment transmettre des accessoires aux routes: component = {() => }


Merci pour l'aide Chris. Je suis juste coincé sur la façon dont je mets un utilisateur sélectionné dans la liste des favoris. Je comprends comment passer des accessoires. @ChrisG


La liste doit être un tableau et faire partie de l ' état du composant de l'application. Ensuite, vous devez transmettre l'identifiant lorsque l'utilisateur clique sur le bouton, afin de savoir quel utilisateur ajouter. onClick = {() => this.props.addToFav (user.id)} . Ajoutez au tableau. Enfin, transmettez le tableau au composant d'itinéraire des favoris.


7 Réponses :


1
votes

Est-ce possible avec React ou ai-je également besoin de Redux?

La plupart sinon tous ces problèmes peuvent être résolus sans redux simplement en utilisant l'état du composant. Il devient de plus en plus difficile de transmettre l’état aux composants qui en ont besoin, plus l’état est global et plus les composants à des profondeurs différentes doivent y accéder et le mettre à jour.

Dans votre cas, il peut suffire de stocker les favoris dans un état de composant en haut de l'arborescence et le transmettent aux composants qui le consomment. Vous pouvez le transmettre directement aux composants ou utiliser le contexte de réaction pour le rendre accessible à composants profondément dans l'arborescence.

Un exemple simple:

const MyComponent = () => {
    const {favorites, add} = useContext(FavoritesContext);

    const [draft, setDraft] = useState('');

    const handleChange = event => setDraft(event.target.value);
    const handleAdd = () => {
        add(draft);
        setDraft('');
    };

    return (
      <div>
          <ul>
              {favorites.map(favorite => <li>{favorite}</li>)}
          </ul>
          <input value={draft} type="text" onChange={handleChange} />
          <button onClick={handleAdd}>Add</button>
      </div>
    );
}

Vous pouvez l'utiliser comme ça:

<FavoritesProvider>
    <MyApp />
</FavoritesProvider>

puis n'importe où dans un composant de votre application:

const FavoritesContext = React.createContext({favorites: []});

const FavoritesProvider = ({children}) => {
    const [favorites, setFavorites] = useState([]);

    const add = useCallback(favorite => setFavorites(current => [...current, favorite]), [setFavorites]);

    return (
        <FavoritesContext.Provider value={{favorites, add}}>
            {children}
        </FavoritesContext.Provider>
};

Dans cet exemple simple, les favoris ne sont que du texte, mais ils pourraient aussi bien être objets. Il montre également comment vous pouvez fournir un gestionnaire pour ajouter un favori. Vous pouvez mettre en œuvre par exemple un gestionnaire pour supprimer les favoris de la même manière.

La persistance de vos favoris est encore un autre sujet que vous devrez peut-être traiter. Vous pouvez utiliser par exemple localStorage pour cela ou vous pouvez stocker cela dans une base de données sur un serveur et le récupérer lorsque votre application se monte pour la première fois.


4 commentaires

Donc, je crée ce dans un fichier séparé et puis je peux mettre mon à l'intérieur? @trixn


@RCohen En gros oui. Le fournisseur injecte un contexte dans l'arborescence en dessous. Tout ce qui est rendu dans le fournisseur y a ensuite accès en utilisant useContext ou en rendant un consommateur de contexte. Il vous suffit de mettre tout ce qui a besoin pour accéder aux favoris. Il n'est pas nécessaire que ce soit toute l'application, mais ce sera souvent le cas.


D'accord, je vais essayer votre solution. @trixn


@RCohen Notez également que même si j'ai utilisé des hooks de réaction ici, cela peut également être fait sans hooks, mais cela nécessite un consommateur de contexte que vous pouvez rendre. Vous pouvez obtenir des détails dans les documents de réaction.



0
votes

Une façon est d'utiliser le stockage local du navigateur.

Mais cette méthode est un peu coûteuse et synchrone.

Mettez à jour la liste chaque fois que l'état de l'élément favori est modifié via

addToFav=user=>{
  const {users}=this.state;
  this.setState({
    users:users.map(userObject=>userObject.id===user.id? 
  {...userObject,isFavorite:!userObject.isFavorite}:user)
    },()=>{saveToLocal(this.state.users)});
}

Et recherchez les éléments favoris via

let users=[{name:"Mr.A",isFavorite:false},{name:"Mr.B",isFavorite:true},...];

Conservez une variable isFavorite dans la liste d'objets.

localStorage.getItem('users');//You need to parse this by JSON.parse()

En cliquant sur le bouton favori this.addToFav changez-le comme suit

localStorage.setItem('users',JSON.stringify(users));

Vous pouvez maintenant accéder les éléments favoris même si la page est rechargée et y reste jusqu'à ce que vous effaciez le stockage. Utilisez ce localStorage.clear () pour cela.


0 commentaires

-1
votes

Premièrement, je changerais votre onClick en ceci:

const favesList = [];
this.state.list.map(listItem => 
    this.state.faves.find(
        faveId => listItem.id === faveId
    ) && favesList.push(item);

Cela vous permettra de passer l'identifiant à la fonction addToFave. Ensuite, j'ajouterais un nouvel état appelé faves (un tableau) et chaque fois que quelqu'un clique sur le bouton Ajouter, j'ajouterais son id dans ce tableau. Cela vous permettra de filtrer votre liste d'origine lorsque vous souhaitez afficher les favoris.

  this.state = {
      list: [],
      faves: [],
    };
  }

  addToFav = (id) => {
    this.setState(prevState => ({
        faves: [...prevState.faves, id],
    }));
  };

Lorsque je veux utiliser la liste des favoris au lieu de la liste normale, je le ferais :

<button onClick={() => this.addToFav(user.id)}>Add to Favorites</button>

Ensuite, je passerais cela au composant faves


1 commentaires

La question est principalement de définir les favoris dans un itinéraire, et de les afficher dans un autre (c'est pourquoi OP demande s'ils ont besoin de redux). Votre réponse ne répond pas à cela.



1
votes

J'ai un peu changé votre fichier, jetez un œil - https://codesandbox.io/ s / clever-butterfly-vb2iz


0 commentaires

2
votes

Voici une boîte à codes qui fonctionne: https://codesandbox.io/s/brave-fire- 4kd4p

Ce train de pensée suit à peu près ce que @Chris G a mentionné. Avoir un état de niveau supérieur contenant la liste des utilisateurs et la liste des favoris. Ensuite, transmettez-les comme accessoires aux composants individuels.

App.js

Appuyez sur votre API ici au lieu de l'intérieur de votre composant UserList pour éviter toute nouvelle rend.

import React from "react";

import NavLinks from "./components/navLink";

export default class FavoriteList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {};
  }

  render() {
    const { favorites } = this.props;
    return (
      <div>
        <NavLinks />
        <ul>
          {favorites.map(user => {
            return (
              <li key={user.id}>
                <div>
                  <img className="thumb" alt="" src={user._links.avatar.href} />
                </div>

                <div className="userInfo">
                  <p>
                    {user.first_name} {user.last_name}
                  </p>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}

} }

UserList.js

Appelez le gestionnaire d'événements addFavorite en cliquant sur le bouton pour renvoyer cet élément au état-parent.

import React from "react";

import NavLinks from "./components/navLink";

export default class UserList extends React.Component {
  render() {
    let style = {
      display: "grid",
      gridTemplateColumns: "repeat(auto-fill, minmax(250px, 1fr))",
      padding: "1rem",
      gridGap: "1rem 1rem"
    };

    return (
      <div>
        <NavLinks />
        <ul style={style}>
          {this.props.list.map(user => {
            return (
              <li key={user.id}>
                <div>
                  <img className="thumb" alt="" src={user._links.avatar.href} />
                </div>

                <div className="userInfo">
                  <p>
                    {user.first_name} {user.last_name}
                  </p>
                </div>
                <button onClick={() => this.props.addFavorite(user)}>
                  Add to Favorites
                </button>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}

Favorite.js

Utilisez le tableau favorites qui a été transmis en tant que accessoire et itérer dessus.

import React, { Component } from "react";
import UserList from "./userList";
import FavoriteList from "./favoriteList";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import axios from "axios";

export default class App extends Component {
  state = {
    list: [],
    favorites: []
  };

  addFavorite = favorite => {
    const { favorites } = this.state;

    if (!favorites.some(alreadyFavorite => alreadyFavorite.id == favorite.id)) {
      this.setState({
        favorites: [...this.state.favorites, favorite]
      });
    }
  };

  getList = async () => {
    const api =
      "https://gorest.co.in/public-api/users?_format=json&access-token=3qIi1MDfD-GXqOSwEHHLH73Y3UitdaFKyVm_";

    await axios
      .get(api)
      .then(response => {
        this.setState({
          list: response.data.result
        });
      })
      .catch(err => {
        console.log(err);
      });
  };

  componentDidMount() {
    this.getList();
  }

  render() {
    return (
      <Router>
        <Switch>
      <Route
        path="/"
        exact
        render={() => (
          <UserList list={this.state.list} addFavorite={this.addFavorite} />
        )}
      />
      <Route
        path="/favorites"
        render={() => <FavoriteList favorites={this.state.favorites} />}
      />
    </Switch>
  </Router>
);


0 commentaires

0
votes

J'ai changé en conséquence, veuillez essayer

https://codesandbox.io/s/ youngful-poincare-7oeh0

la clé est que vous pouvez utiliser l'état push sur votre lien comme ci-dessous

this.props.location.state.favList

plus tard sous votre page fav appeler pour récupérer l'état

<Link to={{ pathname: "/favorites", state: { favList: this.props.favList }}} onClick={() => this.forceUpdate()}>


0 commentaires

0
votes

J'ai un peu changé le code en utilisant le contexte de réaction. Je n'utiliserais pas redux pour cette cause, je pense que ce serait exagéré. Quoi qu'il en soit, voici le bac à sable mis à jour ...

Lien pour le bac à sable


0 commentaires