redux不知道为什么总是自动更新状态,而不是触发

注释大家就不要看了,都是我乱注释的感觉应该有错的···

index.js

import 'core-js/fn/object/assign';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/Main';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
import todoApp from 'stores/reducers.js';

let store = createStore(todoApp);

// Render the main component into the dom
ReactDOM.render(
  <Provider store = {store}>
    <App />
  </Provider>,
  document.getElementById('app')
);

main.js

require('normalize.css/normalize.css');
require('styles/App.css');

import React from 'react';
import {connect} from 'react-redux';
import {changeStyle} from '../actions/actions.js'

import yeomanImage from '../images/yeoman.png'
//let yeomanImage = require('../images/yeoman.png');

class AppComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  handleClick(e){
    this.props.changeStyles;
  }
  render() {
    //从组件的props属性中导入actions里的方法和一个变量
    const {dispatch,propsStyle} = this.props;

    return (
      <div className="index">
        <img src={yeomanImage} alt="Yeoman Generator" />
        {propsStyle}
        {/*<div style={stateStyle} onClick={this.handleClick.bind(this)}>Please edi to get started!</div>*/}
        <div  changeStyle={dispatch(changeStyle())} onClick={this.handleClick.bind(this)}>Please edi to get started!</div>
      </div>
    );
  }
}

function select(state) {
  return {
    //将我们需要的state中的数据绑定到props上
    propsStyle:state.propsStyle
  }
}

 export default connect(select)(AppComponent);
//export default AppComponent;

action.js

/**
 * Created by zhangpeng on 2016/9/18.
 */
export const change = 'change';

export function changeStyle() {
  return {type:change}
}

reducer.js

import {combineReducers} from 'redux';
import {change} from '../actions/actions.js'

function propsStyle(state=0,action) {
  switch (action.type){
    case change:
      return state +1
    default:          //必须有
      return state
  }

}
const todoApp = combineReducers({
  propsStyle       //这个属性名propsStyle必须和函数propsStyle同名  表示通过这个函数处理后的state的值为state.propsStyle  connect会将state.propsStyle赋值到props
})
export default todoApp;

我也不知道是哪里理解错了,直接显示了最终结果,而且报了很多下边的错误
图片描述

大神救救我,我看了很久了都没搞懂这个····

阅读 3.9k
4 个回答

不要在 render 里去改变状态,说的就是这里changeStyle={dispatch(changeStyle())}

因为没有全部的代码,我只能猜你是要作简单的练习而已。所以用你给的代码来测试为何会造成无穷的不断错误讯息。

原因是出在main.js的render方法中的这一行:

<div changeStyle={dispatch(changeStyle())} onClick={this.handleClick.bind(this)}>Please edi to get started!</div>

这一行出了什么错误,以下为我的见解。

首先最严重的是changeStyle={dispatch(changeStyle())},div元素并没有这个属性,就算用已有属性,例如style或data-style,最后渲染出来的必定是个数值,像字串或物件之类的,但在花括号你给的是个dispatch(changeStyle()),所以render方法会去求值出来,dispatch是什么,是一个redux提供给我们的发送动作的方法,藉由发送动作,去改变了全域中的store中的状态,然后作setState,进而促使重新渲染。所以这里面有隐含的setState方法呼叫,这样的作法自然是错误的,为何?因为setState本身就是个会发送re-render的方法,也就是会重新呼叫render方法的方法,你放在render里,造成了一个递回,也就是会一直在重渲染重渲染…然后超出呼叫限制。这样应该能理解问题所在。

那么,这个应用的正确写法应该是如何?

如果你是要按了div元素后,把{propsStyle}呈现出来,也就是按一次+1一次(从你的reducer中)看起来是这样。你应该直接在onClick中直接调用dispatch即可,像下面这样的改法:

{propsStyle}
<div onClick={()=>dispatch(changeStyle())}>Please edi to get started!</div>

用箭头函式是很巧妙的地方,因为onClick是个事件,能指定给它的必须要是个函式,是个准备要让事件触发时执行的函式,dispatch(changeStyle())的回传值不是个函式,而是被发送的动作物件,按逻辑上的作法是在触发时发送对应动作出去,所以包在箭头函式中这样。这是redux的一贯作法,固定的就这样作,用多了你就习惯了。

原本的写法还有一个大问题,算得上是个反样式(anti-pattern),就是在render的回传中进行事件的绑定,说的是下面这行:

onClick={this.handleClick.bind(this)}

在render中绑定事件为何会是个反样式,也就是不建议的作法,因为你每次重渲染就会再绑定一次,实际上在重渲染时会又产生了新的一个函式,所以这个反样式用了会影响效能就是。

正确的使用方式是要预先绑定,有两个绑定方式,第一种是在类的constructor绑定,另一种是使用箭头函式的方式来定义函式。不过这算常见的一个常犯毛病,今天刚好有回答到一个相似的问题,你可以参考: https://segmentfault.com/q/10...

render 希望纯输入输出,不产生其他副作用。楼上的同学回答的很好,我就不好多说了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏