【问题标题】:Simple state update event with Redux using ReactJS?使用 ReactJS 的 Redux 的简单状态更新事件?
【发布时间】:2016-03-31 04:12:38
【问题描述】:

我已经阅读了许多 Redux 和 ReactJS tuts。我理解设置动作 => 动作创建者 => 调度 => 存储 => 渲染视图(单向流)具有更多数据实质性事件。我的问题是处理改变状态的非常简单的事件。我知道并非所有状态都需要在 Redux 中处理,并且本地状态事件(在 React 组件上设置)是一种可接受的做法。但是,从技术上讲,Redux 可以处理所有状态事件,这就是我想要做的。

这就是问题所在。我有一个呈现按钮的 React 组件。此 Button 有一个触发 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}
   }
})

如果有帮助,这里是呈现两个 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>
    );
  }
}

最后,这是包含 store 和与 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。我觉得我导入的功能需要充当调度员。我也觉得我的初始操作设置不正确。这是一个非常简单的事件,以至于在网上任何地方都很难找到答案。有人对我可以做些什么来解决这个问题有任何想法吗?

【问题讨论】:

    标签: javascript events reactjs state redux


    【解决方案1】:

    你快到了。看起来您已经遗漏了Layout 组件的代码,我假设它是呈现您的Button 的组件。这里的关键部分将是你的容器,它是用 Redux 的connect 包装的组件,以将其链接到storeDocs for thisMore details here.

    你做了什么:

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

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

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

    【讨论】:

      猜你喜欢
      • 2016-11-27
      • 1970-01-01
      • 1970-01-01
      • 2019-09-28
      • 2022-01-14
      • 2019-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多