M
M
Maksipes2019-07-18 16:08:51
React
Maksipes, 2019-07-18 16:08:51

Do they do this in React?

Continuation of the question - Do they do this in Reacte?
There I was convinced that a single handler for all Item elements is not good.
I decided to make separate ones, in general, it’s even more convenient than the fuss in Select.
But the question remains of forwarding links to handlers through Props, when there are several of them - it clutters up the code.
I tried to do this:
In the App component, I collect all the links into an object and pass it down the hierarchy.

<ItemsList items={items} handlers={this.aBunchOfHandlers}/>

  get aBunchOfHandlers() {
    return { onTextClick: this.onTextClick, onHintClick: this.onHintClick, onExtaClick: this.onExtaClick };
  }

On the spot, in Aitim, I do this:
export default class Item extends React.Component {
  render() {
    const { item, index, handlers } = this.props;
    return (
      <div className="item">
        <div className="item-over">...</div>
        <div className="item-main">
          <div className="item-text" onClick={handlers.onTextClick.bind(this, index)}>...</div>
          <div className="item-hint"  onClick={handlers.onHintClick.bind(this, index)}>...</div>
          <div className="item-extra" onClick={handlers.onExtraClick.bind(this, index)}>...</div>
        </div>
      </div>
    );
  }
}

And again, the question is - is this normal in React?
And yet - what is better here - bind or arrow function?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Spirin, 2019-07-18
@maksipes

It's better not to do that either. This design is less readable and harder to change. Handlers are best passed explicitly.
Let's take a closer look at a more realistic case:

const Comment = ({ comment, meta, author, postLike, me }) => {
  const [shouldShowReply, setReply] = useState(false);

  const toggleReply = useCallback(() => {
    setReply(s => !s);
  }, []);

  const handleLikeClick = useCallback(() => {
    postLike(comment.id, me.id);
  }, []);

  const isLiked = useMemo(
    () => meta.likes.some(like => like.user_id === me.id),
    [meta.likes],
  );  

  return (
    <Wrapper>
      <Avatar src={user.avatar} to={`/users/${user.slug}`} />
      <CommentBody text={comment.body} />
      <Icon name="like" isActive={isLiked} onClick={handleLikeClick} />
      <Button type="link" onClick={toggleReply}>Reply</Button>
      {shouldShowReply && <ReplyForm />}
    <Wrapper/>
  );
}

const mapStateToProps = (state, ownProps) => ({
  me: meSelector(state),
  author: commentAuthorSelector(state, ownProps),
  meta: commentMetaSelector(state, ownProps),
});

const mapDispatchToProps = {
  postLike,
};

export default connect(mapStateToProps, mapDispatchToProps)(Comment);

See what we get, our comment processes the click on the avatar and clicks on the Like and Reply buttons.
The click on the avatar is processed by the router link, and thanks to the composition, the implementation is hidden from us and we just know that it is enough to pass the src of the picture and the link to the avatar.
The like click is handled by an asynchronous action function that is connected using the connect HOC.
The Reply click is handled by the component's internal handler and changes its state.
At the output, we have an interface for a comment connected to the storage of the following form:
For not connected:
<Comment
  me={me}
  author={author}
  meta={commentMeta}
  postLike={postLike}
  comment={comment}
/>

The flat structure allows us to analyze the code faster in the first place.
Secondly, without unnecessary gestures, change it, decompose it, connect it to the state management library, and so on.
Getters and setters should never be used unnecessarily. Since they, again, complicate the analysis. The exception is the use of tools that welcome their use.
It's in the documentation .

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question