Javascript 未激发操作-react redux反例
我正在尝试用redux设置我的react项目,下面是一个带有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
计数器的基本示例,我可以递增和递减计数器。计数器最初在页面上正确显示为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函数中。。请查看更新的答案。