0
votes

I am unable to dispatch action when I fetch data from the api. I am trying to make a simple todoapp using react and redux and fetching data using api. From api endpoint I return an array of tasks and id.

    import React from 'react';
    import ReactDOM from 'react-dom';


    import  {createStore, applyMiddleware,compose} from 'redux';
    import thunk from 'redux-thunk';
    import {Provider} from 'react-redux';
    import logger from 'redux-logger';
    import reducers from './reducers/index';

    import {startSetTasks} from './actions/AddTask';
    import registerServiceWorker from './registerServiceWorker';
    import './index.css';
    import App from './App';
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

    const store = createStore(reducers,composeEnhancers(applyMiddleware(thunk)));


    const jsx=(
    <Provider store={store}>
    <App/>
    </Provider>);
    ReactDOM.render(<p>Loading...</p>, document.getElementById('root'))

    store.dispatch(startSetTasks()).then(() => {
        ReactDOM.render(jsx, document.getElementById('root'));
      }); 

action generator: I am fetching all the data from api and trying to dispatch the setTasks() but it says actions must be plain objects even after using redux-thunk

        export const setTasks= (tasks)=>{
         type:'SET_TASKS',
         tasks
     }

    export const startSetTasks = ()=>{
        return (dispatch)=>{
          return fetch('http://localhost:4000/todo')
           .then((res)=>{
               return res.json()
           })
           .then((d)=>{
            const tasks=[];
            d.map((data)=>{
                tasks.push({
                    id:data._id,
                    task:data.task
            })

            });
            console.log('tasks ',tasks);
           dispatch(setTasks(tasks))

           }) 
        }
    };         

Component: I am displaying all the tasks. I tried to send return data from startsetTasks() as props using connect

    import React from 'react';
    import {connect} from 'react-redux';
    import Task from './Task';
    import uuid from 'uuid';
    import {startSetTasks, startAddTask} from '../actions/AddTask'
    class TaskList extends React.Component {

        render() {


            return (
                <div>
                    <table>
                        <thead>
                            <tr>
                                <th>Tasks</th>
                                <th>Actions</th>

                            </tr>
                        </thead>
                        <tbody>
                            {this.props.tasks.map(({task,id})=>{
                                return <Task key={uuid()} task={task} id={id} />
                            })}
                        </tbody>
                    </table>
                </div>
            );
        }
    }

    const mapStateToProps = (state)=>{
        return{
            tasks:startSetTasks()
        }
    }

    export default connect(mapStateToProps)(TaskList);

reducers

switch(action.type)
    {
        case 'ADD_TASK': return  [...state, action.val];


        case 'DELETE_TASK': return state.filter(({id})=>{


            return id!==action.id;

        });
        case 'SET_TASKS':{
            return action.tasks
        }


        default: return state;
    }

};

const reducers= combineReducers({
    tasks:taskReducer
});
1

1 Answers

0
votes

It is happens because your binding actions is wrong. You try to bin actions as properties, not as actions in your component. Here is right code example:

import React from 'react';
import { connect } from 'react-redux';
import Task from './Task';
import uuid from 'uuid';
import { startSetTasks, startAddTask } from '../actions/AddTask'

class TaskList extends React.Component {
 componentDidMount() {
   this.props.startAddTask();
 }

 render() {
   return (
  <div>
    <table>
      <thead>
      <tr>
        <th>Tasks</th>
        <th>Actions</th>

      </tr>
      </thead>
      <tbody>
      {this.props.tasks.map(({ task, id }) => {
        return <Task key={uuid()} task={task} id={id}/>
      })}
      </tbody>
    </table>
  </div>
   );
 }
}
 const mapStateToProps = (state) => {
  return {
   tasks: state.tasks
  }
 };

  export default connect(mapStateToProps, { startAddTask })(TaskList);

Pay attention about my component export statement;