Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fetch data by existing redux action with hooks?

I'm trying to understand React Hooks. What I want is to fetch data inside functional component by call redux action with useEffect hooks. I know that I can pass props to state like

 const [todoList] = useState(props.todoList)

But what is the best practice to fetch data by existing redux actions?

In React class component i call this method to fetch data in componentDidMount() and everythink works.

import React, { useEffect } from 'react'
import { connect } from 'react-redux'
import { ITodo } from './types'
import { getTodos } from '../actions/todoActions'

interface IProps {
    todoList: Array<ITodo>

    getTodos: typeof getTodos
}


const Todos = (props: IProps) => {

    useEffect(() => {
          props.getTodos()
    }, [props.todoList])



    return (
         <div>
             {props.todoList.map((_) => (<div key={_.Id}>{_.Name}</div>))}
         </div>
      )
 }

 const mapStateToProps = (state) => ({
     todoList: state.todo.todoList
 })

 const mapDispatchToProps = {
     getTodos
 }


  export default connect(mapStateToProps, mapDispatchToProps)(ProdRoute)

I expected to get list of todos with props and props.getTodos() should call once like in componentDidMount() method. But actualy I get data and getTodos() are called over and over again but should be called once on component mount

like image 354
Masaj Avatar asked Feb 11 '19 14:02

Masaj


1 Answers

Take care that if you pass [props.todoList] to the useEffect you are erroneously forcing a constant refresh because:

  • useEffect does an instance comparison (===) to know if props.todoList is changed
  • after the the very first render the props.getTodos() dispatcher is called
  • when the props.todoList will be updated the component is re-rendered
  • the useEffect call will receive [props.todoList] as a value to check if it needs to re-run or not
  • props.todoList is changed (it was empty and now it's valorized) and props.getTodos() is so re-called
  • redux updates the todoList with the same values but mutating the array reference
  • the component is re-rendered and the useEffect will check if the [props.todoList] param is been updated... but IT IS BEEN UPDATED because the previous props.todoList is different from the actual props.todoList, even if the content is the same

So, if you need to call the props.getTodos() just once can

  • use [props.todoList.length] instead of [props.todoList] as the second parameter for the useEffect call
  • use an empty array [] as the second parameter for the useEffect call (see the docs)
like image 175
NoriSte Avatar answered Sep 30 '22 15:09

NoriSte