Reputation: 405
I am new to react. I want to confirm the input JSON is valid or not and show that on scree. The action ValidConfiguration is being fired and reducer is returning the new state but the smart component add-config-container is not being re-rendered
Here are my files: Action
import {
VALID_CONFIGURATION,
INVALID_CONFIGURATION,
SAVE_CONFIGURATION,
START_FETCHING_CONFIGS,
FINISH_FETCHING_CONFIGS,
EDIT_CONFIGURAION
} from '../constants';
function validateConfiguration(jsonString) {
try {
JSON.parse(jsonString);
} catch (e) {
return false;
}
return true;
}
export function isConfigurationValid(state) {
if (validateConfiguration(state.jsonText)) {
return({type: VALID_CONFIGURATION, state : state});
} else {
return({type: INVALID_CONFIGURATION, state : state});
}
}
export function fetchConfiguration() {
return ({type : START_FETCHING_CONFIGS});
}
export function finishConfiguration(configs) {
return ({type : FINISH_FETCHING_CONFIGS, configs: configs});
}
export function editConfiguration(index) {
return ({type : EDIT_CONFIGURATION, index : index});
}
export function saveConfiguration(config) {
return ({type: SAVE_CONFIGURATION, config : config});
}
Container component
import React, {Component} from 'react';
import {Button, Input, Snackbar} from 'react-toolbox';
import {isConfigurationValid, saveConfiguration} from '../../actions/config';
import { connect } from 'react-redux';
import style from '../../theme/layout.scss';
class AddConfigContainer extends Component {
constructor(props) {
super(props);
this.state = {jsonText: '', key: '', valid: false, showBar : true};
}
handleChange(text, value) {
this.setState({[text]: value});
}
handleSnackbarClick() {
this.setState({ showBar: false});
};
handleSnackbarTimeout() {
this.setState({ showBar: false});
};
render() {
let {onValid} = this.props;
return (
<div>
<h4>Add Configs</h4>
<span>Add configs in text box and save</span>
<Input type='text' label='Enter Key'
value={this.state.key} onChange={this.handleChange.bind(this, 'key')} required/>
<Input type='text' multiline label='Enter JSON configuration'
value={this.state.jsonText} onChange={this.handleChange.bind(this, 'jsonText')} required/>
<div>IsJSONValid = {this.state.valid ? 'true': 'false'}</div>
<Snackbar action='Dismiss'
label='JSON is invalid'
icon='flag'
timeout={2000}
active={ this.state.showBar }
onClick={this.handleSnackbarClick.bind(this)}
onTimeout={this.handleSnackbarTimeout.bind(this)}
type='accept'
class = {style.loader}
/>
<Button type="button" label = "Save Configuration" icon="add" onClick={() => {onValid(this.state)}}
accent
raised/>
</div>
);
}
}
const mapStateToProps = (state) => {
let {
jsonText,
key,
valid
} = state;
return {
jsonText,
key,
valid
};
};
const mapDispatchToProps = (dispatch) => {
return {
onValid : (value) => dispatch(isConfigurationValid(value)),
saveConfiguration: (config) => dispatch(saveConfiguration(config))
}
};
export default connect(mapStateToProps, mapDispatchToProps)(AddConfigContainer);
Reducer
import assign from 'object.assign';
import {VALID_CONFIGURATION, INVALID_CONFIGURATION} from '../constants';
const initialState = {
jsonText : '',
key : '',
valid : false,
showBar: false,
configs: [json],
activeConfig : {},
isFetching: false
};
export default function reducer(state = initialState, action) {
if (action.type === VALID_CONFIGURATION) {
return (assign({}, state, action.state, {valid: true}));
} else if (action.type === INVALID_CONFIGURATION) {
return assign({}, state, action.state, {valid: false});
} else {
return state;
}
}
Upvotes: 0
Views: 102
Reputation: 4704
I think your component does re-render, but you never actually use the valid
value from props (i.e. this.props.valid
). You only use this.state.valid
, but that is not changed anywhere in the code. Note that Redux won't (and can't) change the component's internal state, it only passes new props to the component, so you need to use this.props.valid
to see the change happen. Essentially, you should consider whether you need valid
to exist in the component's state at all. I don't think you do, in this case all the data you have in state (except perhaps showBar
) doesn't need to be there and you can just take it from props.
If you do need to have them in state for some reason, you can override e.g. componentWillReceiveProps
to update the component's state to reflect the new props.
Upvotes: 1