# Redux Tutorial: Define Actions

Step 1: Create redux-todolist/src/redux/actions/todos.js

Let us start by creating a new action file: redux-todolist/src/redux/actions/todos.js. Paste the following code into the newly created file:


import {
  ALL_TODOS,
  EDIT_TODO,
  CREATE_TODO,
  SINGLE_TODO,
  REMOVE_TODO,
} from './actionTypes';

import axios from 'axios';

import GraphQLSettings from '../../../graphql.json';

let GraphQLEndpoint = GraphQLSettings.development.endpoint;

if (process.env.NODE_ENV === 'production') {
  GraphQLEndpoint = GraphQLSettings.production.endpoint;
}

function getTodos() {
  let query = `
    query getTodos {
      todos {
        _id
        todo
        completed
      }
    }
  `;

  return dispatch => {
    return axios.post(GraphQLEndpoint, {
      query
    }).then((result) => {
      if (result.data.errors) {
        dispatch({
          type: ALL_TODOS,
          error: result.data.errors,
        })
        return;
      }

      dispatch({
        type: ALL_TODOS,
        result: result.data.data.todos,
      });
    });
  };
}

function getTodo(variables) {
  let query = `
    query getTodo($_id: String!) {
      todo(_id: $_id) {
        _id
        todo
        completed
      }
    }
  `;

  return dispatch => {
    return axios.post(GraphQLEndpoint, {
      query,
      variables,
    }).then((result) => {
      if (result.data.errors) {
        dispatch({
          type: SINGLE_TODO,
          error: result.data.errors,
        });
        return;
      }

      dispatch({
        type: SINGLE_TODO,
        result: result.data.data.todo,
      });
    })
  };
}

function createTodo(variables) {
  let query = `
    mutation createTodoMutation($todo: String!) {
      createTodo(todo: $todo) {
        _id
        todo
        completed
      }
    }
  `;

  return dispatch => {
    return axios.post(GraphQLEndpoint, {
      query,
      variables,
    }).then((result) => {
      if (result.data.errors) {
        dispatch({
          type: CREATE_TODO,
          error: result.data.errors,
        })
        return;
      }

      dispatch({
        type: CREATE_TODO,
        result: result.data.data.createTodo,
      });
    });
  };
}

function updateTodo(variables) {
  let query = `
    mutation updateTodoMutation($_id: String!, $todo: String, $completed: Boolean) {
      updateTodo(_id: $_id, todo: $todo, completed: $completed) {
        _id
        todo
        completed
      }
    }
  `;

  return dispatch => {
    return axios.post(GraphQLEndpoint, {
      query,
      variables,
    }).then((result) => {
      if (result.data.errors) {
        dispatch({
          type: EDIT_TODO,
          error: result.data.errors,
        })
        return;
      }

      dispatch({
        type: EDIT_TODO,
        result: result.data.data.updateTodo,
      });
    });
  };
}

function removeTodo(variables) {
  let query = `
    mutation removeTodoMutation($_id: String!) {
      removeTodo(_id: $_id) {
        _id
      }
    }
  `;

  return dispatch => {
    return axios.post(GraphQLEndpoint, {
      query,
      variables
    }).then((result) => {
      if (result.data.errors) {
        dispatch({
          type: REMOVE_TODO,
          error: result.data.errors,
        })
        return;
      }

      dispatch({
        type: REMOVE_TODO,
        result: result.data.data.removeTodo,
      });
    });
  };
}

module.exports = {
  getTodo,
  getTodos,
  createTodo,
  updateTodo,
  removeTodo,
};

Let's breakdown the above code:

  • We first begin by importing all the action types we defined in the previous section.
  • We then import the axios module which is a Promise based HTTP client that runs on both browser and NodeJS (Read more about it here: https://github.com/mzabriskie/axios).
  • Then, we import the GraphQL Settings stored in redux-todolist/graphql.json. If you inspect the graphql.json file you'll notice that it defines an endpoint for development and production. Before deploying to your host, make sure you change the production endpoint to point to the public GraphQL API endpoint (must be a fully-qualified domain).
  • We then define 5 actions: getTodo({ id }), getTodos(), createTodo({ todo }), updateTodo({ _id, todo, completed }) and removeTodo({ _id }). These actions execute GraphQL queries and pass in variables when a particular action needs to mutate/fetch a todo item. The result from the execution of these queries is then dispatched to the reducers which in turn set the new state for the UI.

Step 2: Import into: redux-todolist/src/redux/actions/index.js

Open redux-todolist/src/redux/actions/index.js and import the actions file defined above. Your index.js file should look something like this:


import todos from './todos';

module.exports = {
  ...todos,
};