0

I'm surprised here. Maybe you can make it clear for me.

Here is a react riddle that I can't understand:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import _ from 'lodash';
import './style.css';

import FavoritesListItem from '../../components/FavoritesListItem';

class Favorites extends Component {
  handleSaveFavorites() {
    console.log(this.props.favoritesList);
  }

  handleClearFavorites() {
    localStorage.clear();
  }

  handleConsoleLogLocalFavorites() {
    console.log('without JSON.parse', localStorage.getItem('lastSavedFavourites'));
    console.log('with JSON.parse',JSON.parse(localStorage.getItem('lastSavedFavourites')));
  }

  render() {
    if (this.props.favoritesList.length === 0) {
      return (
        <p className="FavoritesListItem-text">
          There are no favorite recipes to show!
        </p>
      );
    }

    const favoritesListGenerator = this.props.favoritesList.map(oneFav => {
      const keyOneFav = _.uniqueId('favorite_');
      return (
        <FavoritesListItem key={keyOneFav} title={oneFav[0]} link={oneFav[1]} />
      );
    });

    return (
      <div>
        <div className="container">
          <div className="row justify-content-xl-center">
            <ul className="col-xl-12">{favoritesListGenerator}</ul>
            <button onClick={this.handleSaveFavorites}>Save</button>
            <button onClick={this.handleClearFavorites}>Clear</button>
            <button onClick={this.handleConsoleLogLocalFavorites}>Local</button>
          </div>
        </div>
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    favoritesList: state.favoritesList,
    readFavorites: state.readFavorites,
  };
}

export default connect(mapStateToProps, null)(Favorites);

Why this.props.favoritesList is working fine and reading data inside favoritesListGenerator, but the same this.props.favoritesList doesn't want to work inside handleSaveFavorites?

Screenshot of an error:

enter image description here

I don't know what else shoud I add so:....


EDIT:

So I added

  constructor() {
    super();
    this.handleSaveFavorites = this.handleSaveFavorites.bind(this);
  }

to my code and now it works!

AND

I think that

<button onClick={() => this.handleSaveFavorites()}>Save</button>

would also work!

MountainConqueror
  • 592
  • 3
  • 7
  • 27
  • @T.J. Crowder: why it is a duplicate? My code is rather unique I think... – MountainConqueror Jan 28 '18 at 17:13
  • 1
    No, it's not at all unique. :-) `this` just isn't what you think it is in the event handler callback, see the linked question's answers for why and what to do about it. This is one of the top five most-duplicated JavaScript questions on the site. – T.J. Crowder Jan 28 '18 at 17:14
  • the function `handleSaveFavorites` creates a new scope hence `this` gets changed.In your case it should be `handleSaveFavorites = () => { console.log(this.props.favoritesList); }` – pritesh Jan 28 '18 at 17:15
  • @pritesh: ***If*** he/she is enabling that particular [Stage 3 proposal](https://github.com/tc39/proposal-class-fields) when transpiling, which he/she may well not be. – T.J. Crowder Jan 28 '18 at 17:17
  • Ok, thank you, guys! :-) – MountainConqueror Jan 28 '18 at 17:17
  • Check this answer as well: [Why is JavaScript bind() necessary?](https://stackoverflow.com/questions/41391288/why-is-javascript-bind-necessary) – Mayank Shukla Jan 28 '18 at 17:19
  • @T.J.Crowder in `favoritesListGenerator` expression arrow function is being used so I think some kind of transipiling is being done. – pritesh Jan 28 '18 at 17:23
  • @pritesh: Not necessary, that's just a normal ES2015 arrow function. The change you suggested above (making the method a class-level property initializer with an arrow function) isn't standardized yet (but it will be soon), see the link for details. (But it's commonly enabled when transpiling React code.) – T.J. Crowder Jan 28 '18 at 17:27
  • Thanks @T.J.Crowder got it. – pritesh Jan 29 '18 at 09:38

0 Answers0