简体   繁体   中英

ReactJs/Redux Maintaining state between reducer calls

Ok, this is a noob question, no doubt, but I couldn't find a good answer in my searches. I've built a simple ReactJs/Redux app and it appears to work fine, except that when I change one value on the page, it blanks out the other in my display of state. What I can't tell is whether the problem is in my display of state or if I'm accidentally mutating state. Advice on best practices and/or debugging in this environment is welcome.

I have a textbox and a drop-down and I display the state (I think). When I change either the dropdown or the text box, the other value goes blank (in my display).

Here's my container:

import { connect } from 'react-redux';
import {
    changeLogFilterMessageContains,
    changeTestDropdownSelectedValue
} from '../actions';
import { LogsPage } from '../components/LogsPage';

const mapStateToProps = (state, ownProps) => ({
    logFilters: state.logFilters,
});

const mapDispatchToProps = {
    changeLogFilterMessageContains,
    changeTestDropdownSelectedValue,
};

const LogsPageContainer = connect(
    mapStateToProps,
    mapDispatchToProps
)(LogsPage);

export default LogsPageContainer;    

and my LogsPage:

import React, {
    Component,
} from 'react';

export class LogsPage extends Component {
    render() {
        return (
            <div>
                <h1>Logs Page</h1>
                <p>Message contains:
                    <input type="text" value={this.props.logFilters.logFilterMessageContains}
                        onChange={e => this.props.changeLogFilterMessageContains({ logFilterMessageContains: e.target.value })} />
                    <br />
                    <select onChange={e => this.props.changeTestDropdownSelectedValue({ testDropdownSelectedValue: e.target.value })}>
                        <option value=""></option>
                        <option value="One">One</option>
                        <option value="Two">Two</option>
                        <option value="Three">Three</option>
                        <option value="Four">Four</option>
                    </select>
                </p>
                <ul>
                    <li>logFilterMessageContains: {this.props.logFilters.logFilterMessageContains}</li>
                    <li>testDropdownSelectedValue: {this.props.logFilters.testDropdownSelectedValue}</li>
                </ul>
            </div>
        );
    }
}

export default LogsPage;

and my reducer:

import { combineReducers } from 'redux';

export const geod = (state = {}, action) => {
    switch (action.type) {
        case 'ACTIVATE_GEOD':
            return action.geod;
        case 'CLOSE_GEOD':
            return {};
        default:
            return state;
    }
};

export const logFilters = (state = {}, action) => {
    switch (action.type) {
        case 'CHANGE_LOG_FILTER_MESSAGE_CONTAINS':
            return action.logFilterMessageContains;
        case 'CHANGE_TEST_DROPDOWN':
            return action.testDropdownSelectedValue;
        default:
            return state;
    }
};

export const reducers = combineReducers({
    geod,
    logFilters
});

And, my actions:

export const activateGeod = geod => ({
    type: 'ACTIVATE_GEOD',
    geod,
});

export const closeGeod = () => ({
    type: 'CLOSE_GEOD',
});

export const changeLogFilterMessageContains = logFilterMessageContains => ({
    type: 'CHANGE_LOG_FILTER_MESSAGE_CONTAINS',
    logFilterMessageContains,
});

export const changeTestDropdownSelectedValue = testDropdownSelectedValue => ({
    type: 'CHANGE_TEST_DROPDOWN',
    testDropdownSelectedValue,
});

I'm sure I'm missing something fundamental, so if someone with the know-how wouldn't mind setting me straight, I would appreciate the help.

V

I have recently learned how to use redux and I have found that this is best place to check yourself: https://egghead.io/courses/getting-started-with-redux . The guy speaking is the grandaddy of redux and he explains the bare bones of it all.

The second thing that I have learned is, make sure you have a test for everything; action creators, reducers, and the store.

Look at your combineReducers , your store's state is going to look something like this

{
    geod: *somevalue*,
    logFilters: *somevalue*
}

The value of logFilters is determined by your logFilters reducer.

Your logFilters reducer returns the action 'payload'. You have called these specific names, logFilterMessageContains & testDropdownSelectedValue, but the returned value will become the value of logFilters in the store's state. You can access this value in your connected component using {this.props.logfilters} (because the structure of your mapStateToProps ).

Looking at the code I don't think that this.props.logFilters.logFilterMessageContains exists in your component. The logFilterMessageContains variable only exists is the scope of your reducer and action creators. The value of this variable sets the value of logFilters in your store's state only after changeLogFilterMessageContains is dispatched.

consider breaking your logFilters reducer into two separate reducers. It looks like you are trying to control two independent variables with it.

any questions?

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