I'm struggling on using react router redux and everything is fine except rendering on props changing.
Index.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 (
);
}
}
ReactDOM.render( , 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 (
)
}
}
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 (
className="input-group">
id="company_number"
value={signData.company_number}
onChange={this.handleInputValue}/>
mdOffset={1} lgOffset={2}
className="input-group">
onUpdate={this.handleInputValue.bind(this, 'data')}/>
|
className="input-group">
onUpdate={this.handleInputValue.bind(this, 'da2')}/>
mdOffset={1} lgOffset={2}
className="input-group">
onUpdate={this.handleInputValue.bind(this, 'dat3')}/>
|
|
)
}
}
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;
someone says that add withRouter
function on export line will fix this error, but it doesn't. (here). However is normally render again when state which is member of SignPaze1
is changed.
How can I fix this problem causd by react-router-redux?
edit
action.js
export const HANDLE_SIGN_INPUT = 'HANDLE_SIGN_INPUT';
export function handleSignInput(target, value){
return {
type: HANDLE_SIGN_INPUT,
target: target,
value: value,
}
}
Answer
I believe the issue here is that you should be using combineReducers
, instead of a single reducer containing nested objects.
You probably need to create a reducer specifically for signData
, and use Redux's combineReducers
method.
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;
}
}
import { combineReducers } from 'redux';
import signDataReducer from './signDataReducer';
export default combineReducers({
signDataReducer
});
The reason it wasn't working before is because of how Object.assign
works, it copies the reference of signData
to the new object created by assign.
Then when the SignPaze1
props are compared by shallow comparison, signData
is the exact same object as before, so is considered equal. And no render occurs.
i.e.
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
No comments:
Post a Comment