2016-09-15 8 views
0

Guten Abend und machen Sie sich bereit für eine Menge Code.Redux Dispatcher funktioniert nicht

Ich lerne, Redux mit React in dem Bemühen zu verwenden, Status über Komponenten zu teilen, und ich habe versucht, eine Navigationsleiste zu erstellen, die Farben basierend auf dem div ändert, auf das Sie klicken. Auf einem hohen Niveau will ich Redux mir erlauben, folgendes zu tun ...

<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> 

Also im Grunde die Komponenten ändern ihre Farbe, wenn Sie darauf klicken, und das ist wirklich schwer in TO reagiere ich bin gekommen, um herauszufinden. Ich habe meinen Dispatcher entsprechend dem Tutorial richtig verkabelt, und ich habe immer noch keinen Erfolg, den Zustand zu ändern. Vielleicht verstehe ich Redux nicht völlig, aber ich würde sicher einige Hilfe schätzen. Ich werde Snippets in der Reihenfolge bereitstellen, die am besten geeignet ist, um mein Problem zu verstehen, und vielleicht kann ich erkennen, wo ich falsch gelaufen bin.

client.js, die mit index.html nichts besonderes verbunden wird.

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) 

Hier ist navReducer.js, die den Ausgangszustand setzt:

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 
} 

Hier ist navActions.js, die eine Aktion hat ...

export function activeBox(){ 
    return{ 
    type: "CLICK", 
    } 
} 

Hier sind die Komponenten, die die obigen Snippets verwenden. Eine Anmerkung, ich erhalte keine Fehler in der Konsole oder im Terminal, was mich glauben macht, dass mein Problem einfach ein schlechter Pfad zu einer Datei ist.

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 (kennzeichnete in 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; 

und schließlich 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; 

Vielen Dank im Voraus Stack-Überlauf-Community, freue ich mich auf Ihre Erkenntnisse, weil Ich habe versucht, den ganzen Tag damit zu arbeiten.

prost

+0

Sie sollten React Dev Tools, nicht nur Chrome Dev Tools verwenden. Könnte von hier installiert werden: https://facebook.github.io/react/blog/2014/01/02/react-chrome-developer-tools.html Ich vermute, Sie werden sehen, dass Ihr Zustand tatsächlich aktualisiert wird. Es wird so etwas wie '{about: ..., projects: ..., active: true}'. – EugZol

+0

@EugZol Ich verwende React Dev Tools und es wird nicht aktualisiert. – m00saca

+0

Würde es Ihnen etwas ausmachen, auch Ihre 'store.js' zu zeigen? – EugZol

Antwort

2

this.props.dispatch(activeBox()); die folgende Aktion zu Ihrem redux Speicher entsendet:

{ 
    type: "CLICK", 
} 

Diese Aktion nicht identifizieren, welche nav Element geklickt wurde, heißt es nur, dass ein Klick aufgetreten. In ähnlicher Weise wird Ihr Minderer gehen von

{ 
    about: { 
    id: "about", 
    title: "Who I am", 
    active: false 
    }, 
    projects: { 
    id: "projects", 
    title: "What I do", 
    active: false 
    } 
} 

zu

{ 
    about: { 
    id: "about", 
    title: "Who I am", 
    active: false 
    }, 
    projects: { 
    id: "projects", 
    title: "What I do", 
    active: false 
    }, 
    active: true 
} 

Sie sind direkt neben about und projects, nicht in ihnen ein aktives Flag hinzuzufügen.Sehen Sie sich das Beispiel redux's todomvc an, um zu sehen, wie Sie am besten erkennen können, auf welchen Artikel geklickt wurde, und Ihr Geschäft entsprechend aktualisieren. Eine Lösung ist

//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

danke für diese gründliche antwort. Ich studiere es jetzt, um zu sehen, wie Sie Ihren Vorschlag am besten als Lösung umsetzen können. Auch danke für den Link zu todomvc Beispiel - hilfreiche Ressource. Also habe ich einen Teil des Ladens auf "{active: true}" eingestellt, aber nicht den Teil, den ich beabsichtigt habe, das verstehe ich jetzt. Ich sehe deinen Kommentar unten in Bezug auf 'nav', der zuerst in der 'reducer'-Funktion gesehen wurde, aber was genau ist das? Ist das ein Verweis auf die '' Ich klicke um 'this.props.dispatch (activeBox) '' auszulösen? – m00saca

+0

Ja, Sie müssen eine Aktion mit dem Typ 'CLICK' versenden sowie eine Identifikation, auf welches Nav geklickt wurde. Ich habe dieses 'nav' genannt, aber es könnte genauso gut' navId' sein oder was auch immer für dich am besten funktioniert. In meinem Beispiel würden Sie 'this.props.dispatch (activeBox (nav)) 'aufrufen, wo Sie tatsächlich in welchem ​​nav es weitergeben, entweder durch ID oder durch String wie' über ' –

+0

Ich implementierte Ihre Lösung und es funktioniert Großartig, vielen Dank. Ich habe versucht, mich mit LocalStorage herumzuschlagen, damit sich die App nach einer Aktualisierung "merkt", in welchem ​​Bereich sie sich befindet. Ist das etwas besser für react-router geeignet oder gibt es eine redux-Lösung? – m00saca