简体   繁体   English

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

[英]Simple state update event with Redux using ReactJS?

I've gone through many of the Redux and ReactJS tuts. 我经历了很多Redux和ReactJS教程。 I understand setting actions => action creators => dispatch => store => render view (uni-directional flow) with more data substantial events. 我了解设置动作=>动作创建者=>调度=>存储=>渲染视图(单向流)具有更多的数据实质性事件。 My problem is dealing with very simple events that change state. 我的问题是处理非常简单的更改状态的事件。 I know not all state always needs to be handled in Redux, and that local state events (set on React components) is an acceptable practice. 我知道并非总是需要在Redux中处理所有状态,并且本地状态事件(在React组件上设置)是可以接受的做法。 However, technically Redux can handle all state events and this is what I am trying to do. 但是,从技术上讲,Redux可以处理所有状态事件,这就是我正在尝试做的事情。

Here is the issue. 这是问题。 I have a React component that renders a Button. 我有一个呈现按钮的React组件。 This Button has an onClick event that fires a handleClick function. 此Button具有一个onClick事件,该事件将触发handleClick函数。 I set the state of the Button via the constructor method to isActive: false. 我通过构造函数将Button的状态设置为isActive:false。 When handleClick fires, setState sets isActive: true. 当handleClick触发时,setState设置isActive:true。 The handleClick method also runs two if statements that, when either evaluate to true, run a function that either changes the background color of the body or the color of paragraph text. handleClick方法还运行两个if语句,当两个语句的任何一个评估为true时,该语句将运行一个函数,该函数更改正文的背景颜色或段落文本的颜色。 Clicking the same button again sets state back to false and will change back the body color or text color to the original value. 再次单击同一按钮,会将状态设置为false,并将主体颜色或文本颜色更改回原始值。 This Button component is created twice within a separate component, Header. 此Button组件在一个单独的组件Header中创建了两次。 So long story short, I've got two buttons. 长话短说,我有两个按钮。 One changes body color, the other changes p tag color after a click event. 一种是更改主体颜色,另一种是在单击事件后更改p标签颜色。

Here's the code for the Button component: 这是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>
    );
  }
}

Here's the code for the imported functions that handle changing the colors: 这是处理颜色更改的导入函数的代码:

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

Here's the code for the reducers: 这是化简器的代码:

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

Here's the code for the actions: 这是操作的代码:

import EasyActions from 'redux-easy-actions';

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

If it helps, here's the Header component that renders two Button components: 如果有帮助,这里的Header组件将呈现两个Button组件:

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

Finally, here's the code containing the store and connection to Redux (NOTE: Layout contains three main components Header, Hero, and Info. The Buttons are created only within the Header component) 最后,这是包含存储和与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>
    );
  }
}

What I am looking to do is remove the state logic from the local React component and into Redux. 我想要做的是将状态逻辑从本地React组件中删除并放入Redux。 I feel like the functions I have imported need to act as dispatchers. 我觉得我导入的功能需要充当调度程序。 I also feel like I am setting up my initial actions incorrectly. 我也觉得我的初始动作设置不正确。 This is such an incredibly simple event that finding an answer anywhere online is difficult. 这是一个非常简单的事件,很难在任何地方在线找到答案。 Anyone have any thoughts on what I can do to fix this? 有人对我可以解决此问题有任何想法吗?

You're almost there. 你快到了。 It looks like you've left out the code for Layout component, which I assume is the component that's rendering your Button . 看来您已经省略了Layout组件的代码,我认为这是呈现Button的组件。 The critical piece here is going to be your container, which is the component that's wrapped with Redux's connect to link it to the store . 这里最关键的部分将是您的容器,该容器是Redux的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: Redux希望您做什么:

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

Hope that helps! 希望有帮助! Redux has a lot of boilerplate for simple stuff like this, however, because most of the pieces can be expressed as pure functions, you gain a lot in unit testing flexibility, and get to use the devtools debugger . Redux对于诸如此类的简单东西有很多样板,但是,因为大多数部分都可以表示为纯函数,所以您在单元测试灵活性上获得了很多,并可以使用devtools调试器

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM