2016-09-15 6 views
0

Хороший вечер и приготовьтесь к большому количеству кода.Диспетчер Redux не работает

Я изучаю, как использовать Redux с React, чтобы разделить состояние между компонентами, и я пытался создать панель навигации, которая меняет цвета, на основе которых вы нажимаете. На высоком уровне, я хочу 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; 

Спасибо заранее переполнению стека сообщества, я с нетерпением жду ваших прозрений, потому что Я пытался заставить его работать весь день.

веселит

+0

Вы должны использовать инструменты React Dev, а не только инструменты Chrome Dev. Может быть установлен здесь: https://facebook.github.io/react/blog/2014/01/02/react-chrome-developer-tools.html Я подозреваю, что вы увидите, что ваше состояние действительно обновляется. Это становится чем-то вроде '{about: ..., projects: ..., active: true}'. – EugZol

+0

@EugZol Я использую React Dev Tools, и он не обновляется. – m00saca

+0

Не могли бы вы также показать свой 'store.js'? – EugZol

ответ

2

this.props.dispatch(activeBox()); отправляет следующие действия в вашем Redux магазине:

{ 
    type: "CLICK", 
} 

Это действие не определить, какие Nav пункт щелкнул, он просто говорит, что щелчок произошел. Точно так же, ваш редуктор будет идти от

{ 
    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 
} 
+0

спасибо за этот тщательный ответ. Я изучаю его сейчас, чтобы узнать, как наилучшим образом реализовать свое предложение в качестве решения. Также благодарим вас за ссылку на источник todomvc - полезный ресурс. Поэтому я установил некоторую часть хранилища в '{active: true}', но не в той части, которую я намеревался, я это понимаю сейчас. Я вижу ваш комментарий внизу относительно 'nav', впервые увиденного в функции' reducer', но что это такое? Это ссылка на '' Я нажимаю, чтобы отключить 'this.props.dispatch (activeBox)'? – m00saca

+0

Да, вам нужно будет отправить действие с типом 'CLICK', а также некоторую идентификацию того, какой навигатор был нажат. Я назвал это «nav», но так же легко было бы «navId» или что-то, что лучше всего подходит для вас. В моем примере вы бы назвали 'this.props.dispatch (activeBox (nav))', где вы на самом деле проходите, в каком навигация это, либо по id, либо по строке, например 'about' –

+0

Я реализовал ваше решение, и оно работает Отлично! Большое спасибо. Я пытался объединиться с localStorage, чтобы приложение «запомнило», в каком разделе он включен после обновления. Это что-то лучше подходит для реактивного маршрутизатора или есть решение для решения? – m00saca

Смежные вопросы