Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Action does not trigger a reducer in React + Redux

I'm working on a react-redux app and for some reason the action I call does not reach the reducer (in which I currently only have a log statement). I have attached the code I feel is relevant and any contributions would be highly appreciated.

Action called within function in component:

onSearchPressed() {
    console.log('search pressed');
    this.props.addToSaved();
}

actions/index.js:

var actions = exports = module.exports

exports.ADD_SAVED = "ADD_SAVED";

exports.addToSaved = function addToSaved() {
  console.log('got to ADD_SAVED step 2');
  return {
    type: actions.ADD_SAVED
  }
}

reducers/items.js:

const {
  ADD_SAVED
} = require('../actions/index')

const initialState = {
    savedList: []
}

module.exports = function items(state = initialState, action) {
    let list

    switch (action.type) {
        case ADD_SAVED:
            console.log('GOT to Step 3');
            return state;
        default:
            console.log('got to default');
            return state;
    }
}

reducers/index.js:

const { combineReducers } = require('redux')
const items = require('./items')

const rootReducer = combineReducers({
  items: items
})

module.exports = rootReducer

store/configure-store.js:

import { createStore } from 'redux'
import rootReducer from '../reducers'

let store = createStore(rootReducer)

EDIT: Entire component for onSearchPressed:

class MainView extends Component {
    onSearchPressed() {
        this.props.addToSaved();
    }
    render() {
        console.log('MainView clicked');
        var property = this.props.property;

        return (
            <View style={styles.container}>
                <Image style={styles.image}
                    source={{uri: property.img_url}} />
                <Text style={styles.description}>{property.summary}</Text>
                <TouchableHighlight style = {styles.button}
                        onPress={this.onSearchPressed.bind(this)}
                        underlayColor='#99d9f4'>
                        <Text style = {styles.buttonText}>Save</Text>
                    </TouchableHighlight>
            </View>
        );
    }
}

module.exports = MainView;
like image 925
user3802348 Avatar asked Apr 22 '16 12:04

user3802348


People also ask

How actions and reducers are connected in Redux?

Reducers, as the name suggests, take in two things: previous state and an action. Then they reduce it (read it return) to one entity: the new updated instance of state. So reducers are basically pure JS functions which take in the previous state and an action and return the newly updated state.

Can we call action in reducer?

Dispatching an action within a reducer is an anti-pattern. Your reducer should be without side effects, simply digesting the action payload and returning a new state object. Adding listeners and dispatching actions within the reducer can lead to chained actions and other side effects.

Which functions are used to trigger an action in Redux?

Redux includes a utility function called bindActionCreators for binding one or more action creators to the store's dispatch() function. Calling an action creator does nothing but return an object, so you have to either bind it to the store beforehand, or dispatch the result of calling your action creator.

Why Redux is not working?

It doesn't work because your action creator is just a function that returns an action. It is up to you to actually dispatch it. We can't bind your action creators to a particular Store instance during the definition because apps that render on the server need a separate Redux store for every request.


1 Answers

Recently I faced issue like this and found that I had used action import but it has to come from props. Check out all uses of toggleAddContactModal. In my case I had missed toggleAddContactModal from destructuring statement which caused this issue.

import React from 'react'
import ReactDOM from 'react-dom'
import Modal from 'react-modal'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import {
  fetchContacts,
  addContact,
  toggleAddContactModal
} from '../../modules/contacts'
import ContactList from "../../components/contactList";

Modal.setAppElement('#root')

class Contacts extends React.Component {
  componentDidMount(){
    this.props.fetchContacts();
  }
  render(){
    const {fetchContacts, isFetching, contacts, 
      error, isAdding, addContact, isRegisterModalOpen,
      toggleAddContactModal} = this.props;
    let firstName;
    let lastName;
    const handleAddContact = (e) => {
      e.preventDefault();
      if (!firstName.value.trim() || !lastName.value.trim()) {
        return
      }
      addContact({ firstName : firstName.value, lastName: lastName.value});
    };

    return (
      <div>
        <h1>Contacts</h1>
        <div>
          <button onClick={fetchContacts} disabled={isFetching}>
            Get contacts
          </button>
          <button onClick={toggleAddContactModal}>
            Add contact
          </button>
        </div>
        <Modal isOpen={isRegisterModalOpen} onRequestClose={toggleAddContactModal}>
          <input type="text" name="firstName" placeholder="First name" ref={node =>         
 (firstName = node)} ></input>
      <input type="text" name="lastName" placeholder="Last name" ref={node => 
(lastName = node)} ></input>
          <button onClick={handleAddContact} disabled={isAdding}>
            Save
          </button>
        </Modal>
        <p>{error}</p>
        <p>Total {contacts.length} contacts</p>
        <div>
          <ContactList contacts={contacts} />
        </div>
      </div>
    );
  }
}
const mapStateToProps = ({ contactInfo }) => {
  console.log(contactInfo)
  return ({
    isAdding: contactInfo.isAdding,
    error: contactInfo.error,
    contacts: contactInfo.contacts,
    isFetching: contactInfo.isFetching,
    isRegisterModalOpen: contactInfo.isRegisterModalOpen
  });
}

const mapDispatchToProps = dispatch =>
  bindActionCreators(
    {
      fetchContacts,
      addContact,
      toggleAddContactModal
    },
    dispatch
  )

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Contacts)
like image 66
Hemant Avatar answered Nov 06 '22 23:11

Hemant