Maksym Popov
Maksym Popov

Reputation: 452

How to call a dispatcher from a functional component?

I've got this functional component. I want to call a dispatcher when .delete is clicked. I've made an example of what I expected to do onClick:

import React from 'react'
import { Link } from 'react-router-dom'

export default function FeedItem(article) {
  return (
    <div className="feed-item flex-column" key={article.id}>
      <Link  to={`/posts/${article.id}`} className="title">{article.title}</Link>
      <div className="delete" onClick={() => dispatch({someType})}>X</div>
      <p>{article.body}</p>
      <Link to={`/edit`} params={{postid: article.id}} className="edit">edit</Link>
    </div>
  )
}

How should it been done right?

Upvotes: 7

Views: 7279

Answers (4)

Alessio Koci
Alessio Koci

Reputation: 1113

You can use HOC or from React 16.8.0 you can also use Hook

HOC

An higher-order component is a function that takes a component and returns a new component with more "features"

Example:

const EnhancedComponent = higherOrderComponent(WrappedComponent);

HOC

React Hooks are functions that let us hook into the React state and lifecycle features from function components.

Example

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0); // useState is an hook

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

HOW?

ANSWER Using HOC

import { connect } from 'react-redux';

function FeedItem({ article, onClick }) {
  return (
    <div className="feed-item flex-column" key={article.id}>
      <Link  to={`/posts/${article.id}`} className="title">{article.title}</Link>
      <div className="delete" onClick={(e) => onClick(e)}>X</div>
      <p>{article.body}</p>
      <Link to={`/edit`} params={{postid: article.id}} className="edit">edit</Link>
    </div>
  )
}

const mapDispatchToProps = dispatch => {
  return {
    // explicitly forwarding arguments
    onClick: event => dispatch({ type: 'SOME_TYPE', payload: event }),
  }
}

export default connect(null, mapDispatchToProps)(FeedItem)

ANSWER Using HOOK

import { useDispatch } from 'react-redux';

export default function FeedItem(article) {
  const dispatch = useDispatch();

  return (
    <div className="feed-item flex-column" key={article.id}>
        <Link to={`/posts/${article.id}`} className="title">{article.title}</Link>
        <div className="delete" onClick={() => dispatch({ someType })}>X</div>
        <p>{article.body}</p>
        <Link to={`/edit`} params={{ postid: article.id }} className="edit">edit</Link>
    </div>
  );
}

DOCS:

  1. react-redux connect hoc
  2. react-redux dispatch hook

Upvotes: 1

Asaf Aviv
Asaf Aviv

Reputation: 11760

You can use useDispatch hook which gives you a reference to the dispatch function

import { useDispatch } from 'react-redux';

export default function FeedItem(article) {
  const dispatch = useDispatch();

  return (
    <div className="feed-item flex-column" key={article.id}>
        <Link to={`/posts/${article.id}`} className="title">{article.title}</Link>
        <div className="delete" onClick={() => dispatch({ someType })}>X</div>
        <p>{article.body}</p>
        <Link to={`/edit`} params={{ postid: article.id }} className="edit">edit</Link>
    </div>
  );
}

Upvotes: 11

Hitmands
Hitmands

Reputation: 14159

you have to connect your component: https://react-redux.js.org/using-react-redux/connect-mapdispatch#defining-mapdispatchtoprops-as-an-object

import React from 'react'
import { Link } from 'react-router-dom'
import { connect } from 'react-router'

function FeedItem(props) {
  return (
    <div className="feed-item flex-column" key={props.id}>
      <Link  to={`/posts/${props.id}`} className="title">{article.title}</Link>
      <div className="delete" onClick={props.dispatchSomething}>X</div>
      <p>{article.body}</p>
      <Link to={`/edit`} params={{postid: article.id}} className="edit">edit</Link>
    </div>
  )
}

const dispatchSomething = data => ({ payload: data, type: 'foo' })

export default connect(null, { dispatchSomething })(FeedItem);

Upvotes: 0

Sultan H.
Sultan H.

Reputation: 2938

Hi Max,

  • First thing you wanna do is connect your component to have an acess to dispatch from redux-thunk.
  • connect will provide the dispatch, and will take an object fo dispatchers, which in this case would be an onClick action.
import React from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';

function FeedItem({ article, onClick }) {
  return (
    <div className="feed-item flex-column" key={article.id}>
      <Link  to={`/posts/${article.id}`} className="title">{article.title}</Link>
      <div className="delete" onClick={(e) => onClick(e)}>X</div>
      <p>{article.body}</p>
      <Link to={`/edit`} params={{postid: article.id}} className="edit">edit</Link>
    </div>
  )
}

const mapDispatchToProps = dispatch => {
  return {
    // explicitly forwarding arguments
    onClick: event => dispatch({ type: 'SOME_TYPE', payload: event }),
  }
}

export default connect(null, mapDispatchToProps)(FeedItem)

Upvotes: 1

Related Questions