首页 文章

Redux使用ReactJS进行简单的状态更新事件?

提问于
浏览
2

我已经完成了许多Redux和ReactJS的讨论 . 我理解设置动作=> action creators => dispatch => store =>渲染视图(单向流),包含更多数据实质性事件 . 我的问题是处理改变状态的非常简单的事件 . 我知道并不是所有的状态总是需要在Redux中处理,并且本地状态事件(在React组件上设置)是可接受的做法 . 但是,从技术上讲,Redux可以处理所有状态事件,这正是我想要做的 .

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

这是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';
      }
    }
}

这是reducer的代码:

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

如果有帮助,这里是呈现两个Button组件的Header组件:

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>
    );
  }
}

最后,这里是包含存储和Redux连接的代码(注意:布局包含三个主要组件Header,Hero和Info . 按钮仅在Header组件中创建)

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>
    );
  }
}

我想要做的是从本地React组件和Redux中删除状态逻辑 . 我觉得我导入的功能需要充当调度员 . 我也觉得我错误地设置了我的初始动作 . 这是一个非常简单的事件,很难在网上找到答案 . 任何人都有任何想法,我可以做些什么来解决这个问题?

1 回答

  • 3

    你're almost there. It looks like you'已经省略了 Layout 组件的代码,我假设它是渲染你的 Button 的组件 . 这里的关键部分将是你的容器,它是's wrapped with Redux' s connect将它链接到 store 的组件 . Docs for this . More details here.

    What you did:

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

    What Redux wants you to do instead:

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

相关问题