简体   繁体   中英

Component not able to re-render when state is changed

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

I think your component does re-render, but you never actually use the valid value from props (ie 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 eg componentWillReceiveProps to update the component's state to reflect the new props.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM