Skip to content

Instantly share code, notes, and snippets.

@Dajust
Last active October 11, 2017 04:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dajust/a0a17990c42d9b5ee27a208b301ad964 to your computer and use it in GitHub Desktop.
Save Dajust/a0a17990c42d9b5ee27a208b301ad964 to your computer and use it in GitHub Desktop.
import React, { Component } from "react";
import { PropTypes } from "prop-types";
import { postData, getLikeBusinessEndpoint } from "../../utils/";
import CheckAuth from "../checkAuth/CheckAuth";
class LikeBusinessButton extends Component {
state = {
isLiked: this.props.isLiked
};
static propTypes = {
isLiked: PropTypes.number.isRequired,
businessId: PropTypes.number.isRequired,
user: PropTypes.object,
location: PropTypes.object.isRequired,
AccessToken: PropTypes.string
};
handleLikeBusiness = () => {
console.log("handleLikeBusiness method in Like.js fired!");
const { isLiked } = this.state;
this.setState(() => ({ isLiked: isLiked == 1 ? 0 : 1 }));
postData(
{},
getLikeBusinessEndpoint(
this.props.businessId,
isLiked == 1 ? 0 : 1,
this.props.AccessToken,
this.props.user.UserId,
// undo the like/unlike if the action was not succesful.
data =>
data.StatusCode != 1 &&
this.setState(() => ({ isLiked: isLiked == 1 ? 0 : 1 }))
)
);
};
render() {
const { isLiked } = this.state;
return (
<CheckAuth user={this.props.user} intentPage={this.props.location.pathname}>
{onCheckAuth => (
<a
onClick={e => {
e.preventDefault();
onCheckAuth(this.handleLikeBusiness);
}}
style={{ color: isLiked == 1 ? "red" : "" }}
className="split nripple-wrapper"
>
<div className="nripple js-ripple">
<span className="nripple__circle" />
</div>
<div className="nlisting-sort-nav sticky-sort-nav">
<i className="icon-heart" />
</div>
</a>
)}
</CheckAuth>
);
}
}
export default LikeBusinessButton;
@Dajust
Copy link
Author

Dajust commented Oct 11, 2017

So line 49 is responsible for swapping red/gray color based on the isLiked variable, from line 42, which is reading from the component state, which in turn is reading from the passed [ isLiked props in line 9.

So we start by hardcoding the isLiked variable to be 1 or 0, to see if the Button actually changes colors.
If that passed, that means the logic in line 50 is fine. Now we proceed to logging, using console.log() what the the isLiked props is actually returning in line 9.
If the props is returning the expected values, it's time to look at somewhere else.
After logging, we found that the props is always returning one value, 0, so the button is never changing its color.

So could it be a problem from the endpoint? Testing the endpoint from PostMan or curl ( I use curl ) we find the endpoint is fine.

So we progress.

On line 48, we're passing to CheckAuth Component the handleLikeBusiness method in line 20, which CheckAuth Component will in turn pass to Authenticate Component, so Authenticate will call the method, when it's done login.

Did all those actually happen? A quick way to find out is to drop a console.log() on the first line of the handleLikeBusiness, that will help us know if the method was ever called.
After that log, we found that the method was actually called. So, probably something is wrong with the method itself.

Looking closely, we see that the handleLikeBusiness is calling some utility function - postData. postData happens to be a function that posts data to the server given the required parameters. So the next question is, is the handleLikeBusiness actually passing the right parameters to postData?

Digging further, we found that none of the parameters are actually changing from what they were before the Authentication was initiated and after the Authentication was completed. Meanwhile, we needed one of those parameters, the this.props.AccessToken on line 31, to change to the new AccessToken returned from the Authentication phase.

A little background on AccessToken parameter. We are using, JWT authentication. So the server always gives a new user a Guest AccessToken that will help him Access/Read/Get the information in the system. But to Write/Post to the system, you'll need a User AccessToken, tied to the logged-in user. So passing that AccessToken, the system will recognize the user performing the like action.

So it appears that the author of the handleLikeBusiness has assumed that after the Authenticate Component is done with login, it will update the App Component with the new AccessToken, then the App Component, in turn, will pass the new AccessToken to the rest of the Components as props. Thinking that the time the handleLikeBusiness is eventually called, the Like Component must have gotten a new AccessToken, the User AccessToken, so it will use to send the Like action.

Unfortunately, there is something called Closure in JavaScript, which is the Author evidently did think of. Closure is the ability of a function to remember it's Lexical Scope even if it's called outside of the lexical scope. Ahh..., if you're not a good JavaScript developer that's jargon. But trust me, there is Closure 😄. The point is, the handleLikeBusiness will still retain or REMEMBER all the value of all variables it references during the time it was called. In our case, it still remembers the old AccessToken props, which is a wrong AccessToken for posting to the system.

To fix it, we'll modify the handleLikeBusiness method to accept AccessToken as a parameter instead of reading it from the props. So let's go fix it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment