Javascript 未激发操作-react redux反例

Javascript 未激发操作-react redux反例,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,我正在尝试用redux设置我的react项目,下面是一个带有计数器的基本示例,我可以递增和递减计数器。计数器最初在页面上正确显示为0,但是当我按下按钮时,增量操作似乎没有被调度,因此计数器不会更新 我的LoginPage.js: /* eslint-disable no-unused-expressions */ import { connect } from "react-redux"; import React, { Component } from "react"; import { se

我正在尝试用redux设置我的react项目,下面是一个带有
计数器的基本示例,我可以递增和递减计数器。计数器最初在页面上正确显示为
0
,但是当我按下按钮时,
增量
操作似乎没有被调度,因此计数器不会更新

我的
LoginPage.js

/* eslint-disable no-unused-expressions */
import { connect } from "react-redux";
import React, { Component } from "react";
import { selectCounter } from "./../../selectors/counter";
import { actions as counterActions } from "./../../actions/counter";

class LoginPage extends Component {
  componentDidMount() {}

  render() {
    const { counter, increment } = this.props;
    return (
      <div>
        <p>{`Hi ${counter}`}</p>
        <button onClick={() => increment()}>+</button>
      </div>
    );
  }
}

LoginPage = connect(
  (state, props) => ({
    counter: selectCounter(state, props)
  }),
  { ...counterActions }
)(LoginPage);

export default LoginPage;
import { INCREMENT } from "./../types/counter";

const increment = () => {
  return { type: INCREMENT };
};

export const actions = {
  increment
};
const { INCREMENT, DECREMENT } = "./../types/counter";

const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case INCREMENT:
      return state + 1;
    case DECREMENT:
      return state - 1;
    default:
      return state;
  }
};

module.exports = { counterReducer };
import { combineReducers } from "redux";
import { counterReducer } from "./counter";

const rootReducer = combineReducers({
  counter: counterReducer
});

export default rootReducer;
import { INCREMENT } from "./../types/counter";
import { useDispatch } from "react-redux";

const increment = () => {
  return { type: INCREMENT };
};

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch(increment())
  };
};

export const actions = {
  ...mapDispatchToProps(useDispatch)
};
My
/reducers/counter.js

/* eslint-disable no-unused-expressions */
import { connect } from "react-redux";
import React, { Component } from "react";
import { selectCounter } from "./../../selectors/counter";
import { actions as counterActions } from "./../../actions/counter";

class LoginPage extends Component {
  componentDidMount() {}

  render() {
    const { counter, increment } = this.props;
    return (
      <div>
        <p>{`Hi ${counter}`}</p>
        <button onClick={() => increment()}>+</button>
      </div>
    );
  }
}

LoginPage = connect(
  (state, props) => ({
    counter: selectCounter(state, props)
  }),
  { ...counterActions }
)(LoginPage);

export default LoginPage;
import { INCREMENT } from "./../types/counter";

const increment = () => {
  return { type: INCREMENT };
};

export const actions = {
  increment
};
const { INCREMENT, DECREMENT } = "./../types/counter";

const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case INCREMENT:
      return state + 1;
    case DECREMENT:
      return state - 1;
    default:
      return state;
  }
};

module.exports = { counterReducer };
import { combineReducers } from "redux";
import { counterReducer } from "./counter";

const rootReducer = combineReducers({
  counter: counterReducer
});

export default rootReducer;
import { INCREMENT } from "./../types/counter";
import { useDispatch } from "react-redux";

const increment = () => {
  return { type: INCREMENT };
};

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch(increment())
  };
};

export const actions = {
  ...mapDispatchToProps(useDispatch)
};
My
/reducers/index.js

/* eslint-disable no-unused-expressions */
import { connect } from "react-redux";
import React, { Component } from "react";
import { selectCounter } from "./../../selectors/counter";
import { actions as counterActions } from "./../../actions/counter";

class LoginPage extends Component {
  componentDidMount() {}

  render() {
    const { counter, increment } = this.props;
    return (
      <div>
        <p>{`Hi ${counter}`}</p>
        <button onClick={() => increment()}>+</button>
      </div>
    );
  }
}

LoginPage = connect(
  (state, props) => ({
    counter: selectCounter(state, props)
  }),
  { ...counterActions }
)(LoginPage);

export default LoginPage;
import { INCREMENT } from "./../types/counter";

const increment = () => {
  return { type: INCREMENT };
};

export const actions = {
  increment
};
const { INCREMENT, DECREMENT } = "./../types/counter";

const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case INCREMENT:
      return state + 1;
    case DECREMENT:
      return state - 1;
    default:
      return state;
  }
};

module.exports = { counterReducer };
import { combineReducers } from "redux";
import { counterReducer } from "./counter";

const rootReducer = combineReducers({
  counter: counterReducer
});

export default rootReducer;
import { INCREMENT } from "./../types/counter";
import { useDispatch } from "react-redux";

const increment = () => {
  return { type: INCREMENT };
};

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch(increment())
  };
};

export const actions = {
  ...mapDispatchToProps(useDispatch)
};
我省略了
App.js
index.js
文件,因为它们非常简单,似乎与问题无关

更新:

我的
操作/counter.js

/* eslint-disable no-unused-expressions */
import { connect } from "react-redux";
import React, { Component } from "react";
import { selectCounter } from "./../../selectors/counter";
import { actions as counterActions } from "./../../actions/counter";

class LoginPage extends Component {
  componentDidMount() {}

  render() {
    const { counter, increment } = this.props;
    return (
      <div>
        <p>{`Hi ${counter}`}</p>
        <button onClick={() => increment()}>+</button>
      </div>
    );
  }
}

LoginPage = connect(
  (state, props) => ({
    counter: selectCounter(state, props)
  }),
  { ...counterActions }
)(LoginPage);

export default LoginPage;
import { INCREMENT } from "./../types/counter";

const increment = () => {
  return { type: INCREMENT };
};

export const actions = {
  increment
};
const { INCREMENT, DECREMENT } = "./../types/counter";

const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case INCREMENT:
      return state + 1;
    case DECREMENT:
      return state - 1;
    default:
      return state;
  }
};

module.exports = { counterReducer };
import { combineReducers } from "redux";
import { counterReducer } from "./counter";

const rootReducer = combineReducers({
  counter: counterReducer
});

export default rootReducer;
import { INCREMENT } from "./../types/counter";
import { useDispatch } from "react-redux";

const increment = () => {
  return { type: INCREMENT };
};

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch(increment())
  };
};

export const actions = {
  ...mapDispatchToProps(useDispatch)
};
现在我看到了错误:

react dom.development.js:14724未捕获错误:钩子调用无效。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一:
1.React和渲染器的版本可能不匹配(例如React DOM)
2.你可能违反了钩子的规则
3.同一应用程序中可能有多个React副本

更新
需要正确定义
mapDispatchToProps
函数并将其传递给
connect()
。在您的代码中,
increment()
似乎没有分派操作

const mapDispatchToProps = (dispatch) =>{
    increment: ()=>dispatch(actions.increment())
}

LoginPage = connect(
  (state, props) => ({
    counter: selectCounter(state, props)
  }),
  mapDispatchToProps
)(LoginPage);
更新
该错误是由于组件外部使用了
useDispatch()
造成的。它必须在功能组件中声明和使用。

但是我仍然能够访问计数器,因为我的选择器执行state=>state.counter-这里的问题在于操作,而不是计数器本身的问题似乎在mapDispatchToProps函数中。。请查看更新的答案。