【问题标题】:Action does not trigger a reducer in React + Redux在 React + Redux 中 Action 不会触发 reducer
【发布时间】:2016-08-16 02:36:51
【问题描述】:

我正在开发一个 react-redux 应用程序,由于某种原因,我调用的操作没有到达 reducer(我目前只有一个 log 语句)。我附上了我认为相关的代码,任何贡献都将受到高度赞赏。

在组件的函数内调用的动作:

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

存储/配置存储.js:

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

let store = createStore(rootReducer)

编辑: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;

【问题讨论】:

  • 检查 onSearchPressed() 上的 console.log(this.props) 并确保它不为空
  • @QoP console.log(this.props) 已正确填充。
  • 这很奇怪!尝试将exports.addToSaved = function addToSaved(){}更改为exports.addToSaved = function (){}
  • @QoP 仍然只到达 action log 语句,而不是 reducer log 语句:\
  • 您没有发送您的操作。 this.props.addToSaved(); 应该是 this.props.dispatch(addToSaved());

标签: javascript ios reactjs react-native redux


【解决方案1】:

正如 Rick Jolly 在您的问题的 cmets 中提到的那样,您的 onSearchPressed() 函数实际上并没有调度该动作,因为 addToSaved() 只是返回一个动作对象 - 它不调度任何东西。

如果你想从一个组件派发动作,你应该使用react-redux 将你的组件连接到redux。例如:

const { connect } = require('react-redux')

class MainView extends Component {
  onSearchPressed() {
    this.props.dispatchAddToSaved();
  }
  render() {...}
}

const mapDispatchToProps = (dispatch) => {
  return {
    dispatchAddToSaved: () => dispatch(addToSaved())
  }
}

module.exports = connect(null, mapDispatchToProps)(MainView)

请参阅'Usage With React' section of the Redux docs 了解更多信息。

【讨论】:

    【解决方案2】:

    最近我遇到了这样的问题,发现我使用了动作导入,但它必须来自道具。查看 toggleAddContactModal 的所有用法。就我而言,我错过了导致此问题的解构语句中的 toggleAddContactModal。

    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)
    

    【讨论】:

    • 我有几次同样的事情,这很烦人,因为它只是默默地失败了。
    • 当一个长大的我几乎要流泪时......经过数小时的调试,解构问题。
    猜你喜欢
    • 2019-01-18
    • 1970-01-01
    • 2019-05-16
    • 2018-11-08
    • 2018-09-03
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多