Redux 调度程序未按预期更改状态
Redux dispatcher does not change state as expected
我正在学习如何将 Redux 与 React 结合使用,以努力在组件之间共享状态,并且我一直在尝试制作一个导航栏,该导航栏会根据您单击 div 来更改颜色。在高层次上,我希望 Redux 允许我执行以下操作...
<Navigation>
<NavEndpt /> <-- click an endpoint and you set this.props.active to true
<NavEndpt /> <-- resets the rest and set this.props.active to false
</Navigation>
所以基本上当你点击它们时组件会改变颜色,这在 React 中真的很难做到,我已经找到答案了。我已根据正在观看的教程正确连接了我的调度程序,但我仍然无法成功更改状态。
可能我对Redux不是很了解。我将按照最适合理解我的问题的顺序提供片段,也许您可以发现我哪里出错了。
client.js
附加到 index.html 没什么特别的。
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import Layout from "./components/Layout"
import store from "./store"
const app = document.getElementById("app");
ReactDOM.render(<Provider store={store}><Layout /></Provider>, app);
store.js
:
import { applyMiddleware, createStore } from "redux";
import reducer from "./reducers/mainReducer"
export default createStore(reducer)
这里是设置初始状态的navReducer.js
:
export default function reducer(state = {
about: {
id: "about",
title: "Who I am",
active: false
},
projects: {
id: "projects",
title: "What I do",
active: false
}
}, action) {
switch (action.type) {
case "CLICK": {
return {...state, active: true }
break
}
}
return state
}
这里是 navActions.js
有一个动作...
export function activeBox(){
return{
type: "CLICK",
}
}
以下是使用上述代码片段的组件。请注意,我在控制台或终端中没有收到任何错误,这让我相信我的问题只是文件路径错误。
Layout.js
import React from "react";
import Nav from "./views/Nav"
import { connect } from "react-redux";
@connect((store) => {
return{
about: store.navControls.about,
projects: store.navControls.projects
};
})
export default class Layout extends React.Component {
render(){
return(
<div id="wrapper">
<Nav about={this.props.about} projects={this.props.projects} dispatch={this.props.dispatch} />
<div id="content"></div>
</div>
)
}
}
Nav.js
(在Layout
中有特色)
import React from "react";
import NavEndpt from "./NavEndpt"
const Nav = React.createClass({
render(){
let about = this.props.about;
let projects = this.props.projects;
return(
<div id="navigation">
<NavEndpt data={about} dispatch={this.props.dispatch} />
<NavEndpt data={projects} dispatch={this.props.dispatch} />
</div>
)
}
})
export default Nav;
最后 NavEndpt.js
import React from "react";
import { activeBox } from "../../actions/navActions.js"
const NavEndpt = React.createClass({
handleClick(){
let data = this.props.data;
console.log("clicked " + data.active)
this.props.dispatch(activeBox()); // this does nothing, checking out React in the chrome dev tools shows no change to about.active or projects.active
},
styleUpdate(){
let data = this.props.data;
if (data.active === false){
return{
background: "violet"
}
} else if (data.active === true){
return {
background: "yellow"
}
}
},
render(){
let data = this.props.data;
return(
<div className="navButton" onClick={this.handleClick} style={this.styleUpdate()}>
<span>{data.title}</span>
</div>
)
}
})
export default NavEndpt;
this.props.dispatch(activeBox());
将以下操作分派到您的 redux 商店:
{
type: "CLICK",
}
该操作不会识别点击了哪个导航项,它只是表示发生了点击。同样,你的 reducer 将从
{
about: {
id: "about",
title: "Who I am",
active: false
},
projects: {
id: "projects",
title: "What I do",
active: false
}
}
到
{
about: {
id: "about",
title: "Who I am",
active: false
},
projects: {
id: "projects",
title: "What I do",
active: false
},
active: true
}
您只是在 about
和 projects
附近添加了一个活动标志,而不是在它们之中。查看 redux's todomvc 示例,了解如何最好地识别哪些项目被点击并适当地更新您的商店。一种解决方案是
//navActions.js
export function activeBox(nav){
return{
type: "CLICK",
nav: nav
}
}
// navReducer.js
export default function reducer(state = {
about: {
id: "about",
title: "Who I am",
active: false
},
projects: {
id: "projects",
title: "What I do",
active: false
}
}, action) {
switch (action.type) {
case "CLICK": {
// Copy state over to prevent altering previous state
let newState = {
about: ...state.about,
projects: ...state.projects
}
// Set all nav items to inactive, when you have more navItems you'll want to loop
newState.about.active = false
newState.projects.active = false
// if action.nav is a proper nav item, set it to active
if (newState[action.nav]) {
newState[action.nav].active = true
}
return newState
break
}
}
return state
}
我正在学习如何将 Redux 与 React 结合使用,以努力在组件之间共享状态,并且我一直在尝试制作一个导航栏,该导航栏会根据您单击 div 来更改颜色。在高层次上,我希望 Redux 允许我执行以下操作...
<Navigation>
<NavEndpt /> <-- click an endpoint and you set this.props.active to true
<NavEndpt /> <-- resets the rest and set this.props.active to false
</Navigation>
所以基本上当你点击它们时组件会改变颜色,这在 React 中真的很难做到,我已经找到答案了。我已根据正在观看的教程正确连接了我的调度程序,但我仍然无法成功更改状态。
可能我对Redux不是很了解。我将按照最适合理解我的问题的顺序提供片段,也许您可以发现我哪里出错了。
client.js
附加到 index.html 没什么特别的。
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import Layout from "./components/Layout"
import store from "./store"
const app = document.getElementById("app");
ReactDOM.render(<Provider store={store}><Layout /></Provider>, app);
store.js
:
import { applyMiddleware, createStore } from "redux";
import reducer from "./reducers/mainReducer"
export default createStore(reducer)
这里是设置初始状态的navReducer.js
:
export default function reducer(state = {
about: {
id: "about",
title: "Who I am",
active: false
},
projects: {
id: "projects",
title: "What I do",
active: false
}
}, action) {
switch (action.type) {
case "CLICK": {
return {...state, active: true }
break
}
}
return state
}
这里是 navActions.js
有一个动作...
export function activeBox(){
return{
type: "CLICK",
}
}
以下是使用上述代码片段的组件。请注意,我在控制台或终端中没有收到任何错误,这让我相信我的问题只是文件路径错误。
Layout.js
import React from "react";
import Nav from "./views/Nav"
import { connect } from "react-redux";
@connect((store) => {
return{
about: store.navControls.about,
projects: store.navControls.projects
};
})
export default class Layout extends React.Component {
render(){
return(
<div id="wrapper">
<Nav about={this.props.about} projects={this.props.projects} dispatch={this.props.dispatch} />
<div id="content"></div>
</div>
)
}
}
Nav.js
(在Layout
中有特色)
import React from "react";
import NavEndpt from "./NavEndpt"
const Nav = React.createClass({
render(){
let about = this.props.about;
let projects = this.props.projects;
return(
<div id="navigation">
<NavEndpt data={about} dispatch={this.props.dispatch} />
<NavEndpt data={projects} dispatch={this.props.dispatch} />
</div>
)
}
})
export default Nav;
最后 NavEndpt.js
import React from "react";
import { activeBox } from "../../actions/navActions.js"
const NavEndpt = React.createClass({
handleClick(){
let data = this.props.data;
console.log("clicked " + data.active)
this.props.dispatch(activeBox()); // this does nothing, checking out React in the chrome dev tools shows no change to about.active or projects.active
},
styleUpdate(){
let data = this.props.data;
if (data.active === false){
return{
background: "violet"
}
} else if (data.active === true){
return {
background: "yellow"
}
}
},
render(){
let data = this.props.data;
return(
<div className="navButton" onClick={this.handleClick} style={this.styleUpdate()}>
<span>{data.title}</span>
</div>
)
}
})
export default NavEndpt;
this.props.dispatch(activeBox());
将以下操作分派到您的 redux 商店:
{
type: "CLICK",
}
该操作不会识别点击了哪个导航项,它只是表示发生了点击。同样,你的 reducer 将从
{
about: {
id: "about",
title: "Who I am",
active: false
},
projects: {
id: "projects",
title: "What I do",
active: false
}
}
到
{
about: {
id: "about",
title: "Who I am",
active: false
},
projects: {
id: "projects",
title: "What I do",
active: false
},
active: true
}
您只是在 about
和 projects
附近添加了一个活动标志,而不是在它们之中。查看 redux's todomvc 示例,了解如何最好地识别哪些项目被点击并适当地更新您的商店。一种解决方案是
//navActions.js
export function activeBox(nav){
return{
type: "CLICK",
nav: nav
}
}
// navReducer.js
export default function reducer(state = {
about: {
id: "about",
title: "Who I am",
active: false
},
projects: {
id: "projects",
title: "What I do",
active: false
}
}, action) {
switch (action.type) {
case "CLICK": {
// Copy state over to prevent altering previous state
let newState = {
about: ...state.about,
projects: ...state.projects
}
// Set all nav items to inactive, when you have more navItems you'll want to loop
newState.about.active = false
newState.projects.active = false
// if action.nav is a proper nav item, set it to active
if (newState[action.nav]) {
newState[action.nav].active = true
}
return newState
break
}
}
return state
}