7

I'm creating a React/Redux front-end for a multi-channel chat app. I'm having problems getting some React components to re-render after state change while using redux, react-redux, and redux-thunk.

I believe that my reducers are non-mutating, and that I'm subscribed via react-redux's connect. When I run the app and view the browser console, I see the initial render of the component (i.e. with initial, empty state), then the state change (triggered by an action dispatch in index.js).... I would then expect the component to re-render with new props, but it doesn't happen.

console log

I've put up a repo here: https://github.com/mattmoss/react-redux-no-update

node_modules is not in the repo, so to run, first download dependencies (running yarn is sufficient), then npm start.

Some excerpts (see full source in repo):

reducers/channelList.js

import * as c from '../actions/constants';

export default function channelList(state = [], action) {
    switch (action.type) {
        case c.FETCH_CHANNELS_SUCCESS:
            return action.channels;
        default:
            return state;
    }
}

actions/channelActions.js

export function fetchChannels() {
    return (dispatch) => {
        return ChannelApi.allChannels()
            .then(channels => dispatch(fetchChannelsSuccess(channels)))
            .catch(error => { throw(error); });
    };
}

export function fetchChannelsSuccess(channels) {
    return {
        type: c.FETCH_CHANNELS_SUCCESS,
        channels
    };
}

components/ChannelListView.js

class ChannelListView extends React.Component {
    render() {
        const { channels, current, onSelect } = this.props;

        console.log("channels:", channels, "current:", current);

        return (
            <ListGroup>
                {channels.map(channel =>
                    <ListGroupItem
                        key={channel.id}
                        active={channel.id === this.props.current}
                        onClick={onSelect(channel.id)}
                    >
                        <strong>#{channel.name}</strong>
                    </ListGroupItem>
                )}
            </ListGroup>
        );
    }
}

export default ChannelListView;

containers/ChannelList.js

import ChannelListView from '../components/ChannelListView';

const mapStateToProps = (state, ownProps) => {
    return {
        channels: state.channelList,
        current: state.currentChannel
    };
};

const mapDispatchToProps = (dispatch) => {
    return {
        onSelect: (id) => () => {}
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(ChannelListView);

App.js

class App extends Component {
  render() {
    return (
      <Grid>
        <Row>
          <Col>
            <h1>Channels</h1>
            <ChannelList />
          </Col>
        </Row>
      </Grid>
    );
  }
}

index.js

const store = configureStore();
store.dispatch(fetchChannels());

ReactDOM.render(
    <Provider store={configureStore()}>
        <App />
    </Provider>,
    document.getElementById('root')
);

store/configureStore.js

import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers/rootReducer';
import thunk from 'redux-thunk';
import logger from 'redux-logger';

export default function configureStore() {
    return createStore(
        rootReducer,
        applyMiddleware(thunk, logger)
    );
}
2
  • can you show configureStore as well? Commented May 9, 2017 at 23:03
  • @MichaelPeyper Edited to show configureStore. Commented May 9, 2017 at 23:07

1 Answer 1

6

I'm not 100% as I am still relatively new to React myself. But look at your index.js script.

// You configure the store, then dispatch the fetchChannels action
const store = configureStore();
store.dispatch(fetchChannels());

ReactDOM.render(
    // But here, you're recreating the store again, which I think will re-initialise an empty store
    // Change this to use the `store` variable from above.
    <Provider store={configureStore()}>
        <App />
    </Provider>,
    document.getElementById('root')
);
Sign up to request clarification or add additional context in comments.

3 Comments

good spotting... I missed this and was getting ready to set up a jsfiddle to try to work this out.
That's it... You know, wearing trifocals, you'd think my "eight eyes" would have seen this, but no.... In the end, I figured it would be something silly. Thanks a bunch!
You're welcome. I couldn't see anything wrong with what you'd written either until I spotted this. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.