【问题标题】:react router redux is not rendered on props changingreact router redux 不会在 props 更改时呈现
【发布时间】:2017-12-15 10:06:11
【问题描述】:

我在使用 react router redux 时遇到了困难,一切都很好,除了在 props 上的渲染发生变化。

索引.js

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore, combineReducers, applyMiddleware} from 'redux';
import {Router, Route, browserHistory} from 'react-router';
import { syncHistoryWithStore, routerReducer, routerMiddleware } from 'react-router-redux';
import App from './app';
import Sign from '../sign/app';
import SignInfo from '../sign/redux/reducer';

let store = createStore(
  combineReducers({
    SignInfo,
    routing: routerReducer
  }),
);

const history = syncHistoryWithStore(browserHistory, store);

class Index extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    console.log('root')
    return (
      <Provider store={store}>
        <Router history={history}>
          <Route path="/" component={App}/>
          <Route path="/sign" component={Sign}/>
        </Router>
      </Provider>
    );
  }
}

ReactDOM.render(<Index/>, document.getElementById('root'));

sign.js

import React from 'react';
import {connect} from 'react-redux';
import Belle from 'belle';
import {Grid, Row, Col} from 'react-flexbox-grid';
import { withRouter } from 'react-router';
import SignPaze1 from './signPaze1'

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const mainCardStyle = {
      border: '1px solid #aaa',
    }
    return (

      <div className="sign-page">
        <SignPaze1/>
      </div>
    )
  }
}

function mapStateToProps(state) {
  return {
  }
}

export default withRouter(connect(mapStateToProps)(App));

signPaze1.js

import React from 'react';
import { bindActionCreators } from 'redux';
import {connect} from 'react-redux';
import Belle from 'belle';
import { withRouter } from 'react-router';
import {Grid, Row, Col} from 'react-flexbox-grid';

import {handleSignInput} from './redux/action';

class SignPaze1 extends React.Component {
  constructor(props) {
    super(props);

    this.handleInputValue = this.handleInputValue.bind(this);

  }

  handleInputValue(e) {
    let {dispatch} = this.props;
    console.log('on render')
    const action = bindActionCreators(handleSignInput, dispatch)
    action(e.target.id, e.target.value);
  }
  render() {
    let signData = this.props.signData;
    let mainCardStyle = {
      border: '1px solid #aaa',
    }
    return (
      <Grid>
        <Row>
          <Col xs={12}>
            <Belle.Card style={mainCardStyle}>
              <Row center="md">
                <Col xs={12} sm={6} md={4} lg={3}
                     className="input-group">
                  <input type="text"
                         id="company_number"
                         value={signData.company_number}
                         onChange={this.handleInputValue}/>
                </Col>
                <Col xs={12} sm={6} md={4} lg={3}
                     mdOffset={1} lgOffset={2}
                     className="input-group">
                  <Belle.TextInput
                    onUpdate={this.handleInputValue.bind(this, 'data')}/>
                </Col>
              </Row>
              <Row center="md">
                <Col xs={12} sm={6} md={4} lg={3}
                     className="input-group">
                  <Belle.TextInput
                    onUpdate={this.handleInputValue.bind(this, 'da2')}/>
                </Col>
                <Col xs={12} sm={6} md={4} lg={3}
                     mdOffset={1} lgOffset={2}
                     className="input-group">
                  <Belle.TextInput
                    onUpdate={this.handleInputValue.bind(this, 'dat3')}/>
                </Col>
              </Row>
            </Belle.Card>
          </Col>
        </Row>
      </Grid>
    )
  }
}

function mapStateToProps(state) {
  console.log(state.SignInfo);
  return {
    signData: state.SignInfo.signData,
  }
}

export default withRouter(connect(mapStateToProps)(SignPaze1));

reducer.js

import {HANDLE_SIGN_INPUT} from './action';

const initialMainState = {
  signData: {
    company_number: 'asdas|',
    company_name: '',
    username: '',
    email: '',
    email_confirm: '',
    password: '',
    password_confirm: '',
  }
}

function SignInfo(state = initialMainState, action) {
  let newVal = {};
  switch (action.type) {
    case HANDLE_SIGN_INPUT:
      newVal = Object.assign({}, state);
      newVal.signData[action.target] = action.value;
      return newVal;
    default:
      return state;
  }
}

export default SignInfo;

有人说在导出行添加withRouter 函数可以解决此错误,但事实并非如此。 (here)。但是,当 SignPaze1 的成员状态发生更改时,通常会再次渲染。

如何解决这个由 react-router-redux 引起的问题?

编辑

action.js

export const HANDLE_SIGN_INPUT = 'HANDLE_SIGN_INPUT';

export function handleSignInput(target, value){
  return {
    type: HANDLE_SIGN_INPUT,
    target: target,
    value: value,
  }
}

【问题讨论】:

  • 更新什么属性时,哪个组件没有重新渲染?
  • @JacobPålsson class SignPaze1 在 signpaze1.js 文件中不会“再次”呈现。(我的意思是,第一次加载页面时,SignPaze1 呈现良好,但在道具更改后,它没有。)我发现console.logmapStateToProps() 中运行良好,但在render() 中却没有,这是SignPaze1 类的成员函数。
  • 你能显示你的action.js文件吗
  • @TomBerghuis 我在我的帖子中添加了action.js 文件。

标签: javascript reactjs react-router react-router-redux


【解决方案1】:

我认为这里的问题是您应该使用combineReducers,而不是包含嵌套对象的单个reducer。

您可能需要专门为signData 创建一个reducer,并使用Redux 的combineReducers 方法。

新文件:signDataReducer.js

import {HANDLE_SIGN_INPUT} from './action';

const initialMainState = {
  company_number: 'asdas|',
  company_name: '',
  username: '',
  email: '',
  email_confirm: '',
  password: '',
  password_confirm: '',
};

export default function SignData (state = initialMainState, action) {
  let newVal = {};
  switch (action.type) {
    case HANDLE_SIGN_INPUT:
      newVal = Object.assign({}, state);
      newVal[action.target] = action.value;
      return newVal;
    default:
      return state;
  }
}

reducer.js

import { combineReducers } from 'redux';
import signDataReducer from './signDataReducer';

export default combineReducers({
  signDataReducer
});

它之前不工作的原因是Object.assign 的工作方式,它将signDatareference 复制到由assign 创建的新对象。

那么当SignPaze1 props 通过浅比较比较时,signData 和之前是完全相同的对象,所以被认为是相等的。并且没有渲染发生。

const initialMainState = {
  signData: {
    company_number: 'asdas|',
    company_name: '',
    username: '',
    email: '',
    email_confirm: '',
    password: '',
    password_confirm: '',
  }
}
const newState = Object.assign({}, initialMainState);


newState.signData.company_name = 'Hello!';
// => "Hello!"
initialMainState.signData.company_name
// => "Hello!"
newState.signData === initialMainState.signData
// => true

【讨论】:

    猜你喜欢
    • 2019-03-11
    • 2016-07-03
    • 2017-09-12
    • 2018-09-04
    • 2016-12-05
    • 2019-11-23
    • 2021-08-19
    • 2018-04-23
    • 1970-01-01
    相关资源
    最近更新 更多