2016-03-31 71 views
2

我已经经历了许多Redux和ReactJS的琐事。我了解设置操作=>操作创建者=> dispatch => store =>渲染视图(单向流),其中包含更多数据实质性事件。我的问题是处理改变状态的非常简单的事件。我知道并不是所有的状态总是需要在Redux中处理,并且本地状态事件(在React组件上设置)是可以接受的做法。但是,技术上Redux可以处理所有状态事件,这就是我正在尝试做的事情。Redux使用ReactJS进行简单状态更新事件?

这是问题。我有一个呈现Button的React组件。此按钮具有触发handleClick函数的onClick事件。我通过构造函数方法将Button的状态设置为isActive:false。当handleClick触发时,setState设置isActive:true。 handleClick方法还运行两个if语句,当它们的值为true时,运行一个函数,该函数会更改主体的背景颜色或段落文本的颜色。再次单击相同的按钮会将状态设置回false,并且会将主体颜色或文本颜色更改回原始值。此Button组件在一个单独的组件Header中创建两次。长话短说,我有两个按钮。一个改变主体颜色,另一个改变点击事件后的p标签颜色。

这里的Button组件的代码:

import React, {Component} from 'react'; 
import {dimLights, invertColor} from '../../../actions/headerButtons'; 
import { connect } from 'react-redux'; 
import { Actions } from '../../../reducers/reducer'; 

const headerButtonWrapper = 'headerButton'; 
const headerButtonContext = 'hb--ctrls '; 
const dimmedLight = '#333333'; 
const invertedTextColor = '#FFFFFF'; 

export default class Button extends Component { 
    constructor (props) { 
    super(props) 
    this.state = { 
     isActive: false 
    }; 
    } 

    handleClick (e) { 
    e.preventDefault(); 
    let active = !this.state.isActive; 
    this.setState({ isActive: active }); 

     if(this.props.label === "Dim The Lights"){ 
     dimLights('body', dimmedLight); 
     } 
     if(this.props.label === "Invert Text Color"){ 
     invertColor('p', invertedTextColor) 
     } 
    } 

    render() { 
    let hbClasses = headerButtonContext + this.state.isActive; 
    return (
     <div className={headerButtonWrapper}> 
     <button className={hbClasses} onClick={this.handleClick.bind(this)}>{this.props.label}</button> 
     </div> 
    ); 
    } 
} 

这里是为处理不断变化的色彩进口函数的代码:

export function dimLights(elem, color) { 
    let property = document.querySelector(elem); 
    if (property.className !== 'lightsOn') { 
     property.style.backgroundColor = color; 
     property.className = 'lightsOn' 
    } 
    else { 
     property.style.backgroundColor = '#FFFFFF'; 
     property.className = 'lightsOff'; 
    } 
} 

export function invertColor(elem, textColor) { 
    let property = document.querySelectorAll(elem), i; 
    for (i = 0; i < property.length; ++i) { 
     if (property[i].className !== 'inverted') { 
      property[i].style.color = textColor; 
      property[i].className = 'inverted' 
     } else { 
      property[i].style.color = '#3B3B3B'; 
      property[i].className = 'notInverted'; 
     } 
    } 
} 

下面是减速机代码:

import * as types from '../constants/ActionTypes'; 

const initialState = { 
    isActive: false 
}; 

export default function Actions(state = initialState, action) { 
    switch (action.type) { 

     case types.TOGGLE_LIGHTS: 
     return [ 
     ...state, 
     { 
      isActive: true 
     } 
     ] 

     default: 
     return state 
    } 
} 

以下是操作的代码:

import EasyActions from 'redux-easy-actions'; 

export default EasyActions({ 
    TOGGLE_LIGHTS(type, isActive){ 
     return {type, isActive} 
    } 
}) 

如果有帮助,这里的头组件呈现两个按钮组件:

import React, {Component} from 'react'; 
import Button from './components/Button'; 

const dimmer = 'titleBar--button__dimmer'; 
const invert = 'titleBar--button__invert'; 

export default class Header extends Component { 
    render() { 
    return (
     <div id="titleBar"> 
     <div className="titleBar--contents"> 
      <div className="titleBar--title">Organizer</div> 
      <Button className={dimmer} label="Dim The Lights" /> 
      <Button className={invert} label="Invert Text Color" /> 
     </div> 
     </div> 
    ); 
    } 
} 

最后,这里是一个包含了存储和连接到终极版(注代码:布局包含三个主要组件头,英雄和Info。该按钮仅在标题组件)

import React, { Component } from 'react'; 
import { combineReducers } from 'redux'; 
import { createStore } from 'redux' 
import { Provider } from 'react-redux'; 

import Layout from '../components/Layout'; 
import * as reducers from '../reducers/reducer'; 

const reducer = combineReducers(reducers); 
const store = createStore(reducer); 

// This is dispatch was just a test to try and figure this problem out 
store.dispatch({ 
    type: 'TOGGLE_LIGHTS', 
    isActive: true 
}) 
console.log(store.getState()) 

export default class Organizer extends Component { 
    render() { 
    return (
     <Provider store={store}> 
      <div> 
      <Layout /> 
      </div> 
     </Provider> 
    ); 
    } 
} 

我所希望做的是从本地删除状态逻辑阵营部件并进入终极版创建的。我觉得我输入的功能需要充当调度员。我也觉得我正在错误地设定我的初始行动。这是一个非常简单的事件,在网上任何地方找到答案都很困难。任何人有任何想法,我可以做些什么来解决这个问题?

回答

3

你快到了。看起来你已经遗漏了Layout组件的代码,我认为它是渲染你的Button的组件。这里的关键部分将成为你的容器,这是Redux的connect将其链接到store的组件。 Docs for thisMore details here.

你做了什么:

// components/Button.js - pseudocode 
import {dimLights, invertColor} from '../../../actions/headerButtons'; 

handleClick() { 
    dimLights(); 
} 

终极版要你做什么,而不是:

// containers/App.js - pseudocode 
import {dimLights, invertColor} from '../../../actions/headerButtons'; 

class App extends Component { 
    render() { 
    // Pass in your button state from the store, as well as 
    // your connected/dispatch-ified actions. 
    return (
     <Button 
     state={this.props.buttonState} 
     onClick={this.props.buttonState ? dimLights : invertColor} 
     /> 
    ); 
    } 
} 

function mapStateToProps(state, ownProps) { 
    return { 
    buttonState: state.buttonState 
    }; 
} 
export default connect(mapStateToProps, { 
    // Your action functions passed in here get "dispatch-ified" 
    // and will dispatch Redux actions instead of returning 
    // { type, payload }-style objects. 
    dimLights, invertColor 
})(App); 

希望帮助! Redux对于这样简单的东西有很多样板,但是,因为大多数部分都可以表示为纯函数,所以在单元测试的灵活性方面你会获得很多,并且可以使用devtools debugger