1

I am a newbie to react. I have a navigation bar like the one below

import React, { Component, PropTypes } from 'react';
import { Navbar, Nav, NavItem } from 'react-bootstrap';
import { LinkContainer } from 'react-router-bootstrap';

class MainNav extends Component {

    constructor(props) {
        super(props);
        this.state = {
         loggedIn: 1,
        };
    }
    render() {
        return (
             <div>
                <Navbar inverse collapseOnSelect>
                    <Navbar.Header>
                        <Navbar.Brand>
                            <a href="/">SportsSpot</a>
                        </Navbar.Brand>
                    <Navbar.Toggle />
                    </Navbar.Header>
                    <Navbar.Collapse>
                        <Nav>
                            <LinkContainer to="/nfl">
                               <NavItem>NFL</NavItem>
                            </LinkContainer>
                            <LinkContainer to="/mlb">
                               <NavItem>MLB</NavItem>
                            </LinkContainer>
                            <LinkContainer to="/nba">
                               <NavItem>NBA</NavItem>
                            </LinkContainer>
                            <LinkContainer to="/nhl">
                               <NavItem>NHL</NavItem>
                            </LinkContainer>   
                        </Nav>
                    <Nav pullRight>
                        <LinkContainer to="/login">
                                <NavItem>Login</NavItem>
                        </LinkContainer>
                        <LinkContainer to="/signup">
                            <NavItem>Sign Up</NavItem>
                        </LinkContainer>
                    </Nav>
                    </Navbar.Collapse>
                </Navbar>
                <div className="content">
                        {this.props.children}
                </div>
            </div>
        )
    }
}

MainNav.propTypes = {
  children: PropTypes.element.isRequired,
};

export default MainNav;

I am trying to dispatch action to the server whenever user clicks on any of the links in the navigation bar so as to fetch the corresponding data. My action creator file looks like the following

export function getCurrentAllNews() {
    return {
        meta: { remote: true },
        type: 'GET_CURRENT_ALL_NEWS'
    };
}

export function getCurrentNBANews() {
    return {
        meta: { remote: true },
        type: 'GET_CURRENT_NBA_NEWS'
    };
}


export function getCurrentNHLNews() {
    return {
        meta: { remote: true },
        type: 'GET_CURRENT_NHL_NEWS'
    };
}


export function getCurrentNFLNews() {
    console.log("it comes here:");
    return {
        meta: { remote: true },
        type: 'GET_CURRENT_NFL_NEWS'
    };
}


export function getCurrentMLBNews() {
    return {
        meta: { remote: true },
        type: 'GET_CURRENT_MLB_NEWS'
    };
}


export function setConnectionState(state, connected) {
    return {
        type: 'SET_CONNECTION_STATE',
        state,
        connected
    };
}

So for example when the user clicks on the link to NFL i want to add something like

<LinkContainer to="/nfl">
      <NavItem onClick={this.props.getCurrentNFLNews} eventKey={1}>NFL</NavItem>
 </LinkContainer>

So that I will be able to dispatch the corresponding action for nfl and fetch the required data from the server

I read that connect from 'react-redux' can be used to connect the callback function with action creators. for that i have to use the code like

export const MainNavContainer = connect(mapNavToProps,actionCreators)(MainNav);

But the problem is connect is not working for a navigation bar which already has some routes defined under it. I.e I have a route file like below

import MainNav from './components/navbar.jsx';
const routes =<MainNav>
    <App>
    <Switch>
        <Route exact path="/" component={HomePageContainer}/>
        <Route exact path="/nfl" component={NFLHomePageContainer}/>
        <Route path ="/login" component = {LoginPage}/>
        <Route path ="/signup" component = {SignUpPage}/>
    </Switch>
    </App> 
</MainNav>;

So, trying to add connect to the navbar.jsx throws the following error

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in.

My index.jsx has the provider code like below

ReactDOM.render((
  <MuiThemeProvider muiTheme={getMuiTheme()}>
    <Provider store={store}>
      <Router>{routes}</Router>
    </Provider>
  </MuiThemeProvider>), 
        document.getElementById('root')
);

I am unaware of how to solve this issue. I would also like to know how to redirect only after receiving the data from the server so that wrong info is not displayed in a new page.Thanks for the help in advance

1 Answer 1

3

Since nature of your action seems to be asynchronous I will suggest you to use "redux-thunk" although it is not absolutely necessary but make things quite easier.

Inside your action creator -

export function updateNHLNewaResults(newsList) {
    return {
        type : UPDATE_NHL_NEWS_RESULTS,
        newsList
    };
}

export function getCurrentNHLNews() {
    return dispatch => {
        return Api.getCurrentNHLNews()
            .then( res => {
                dispatch(updateNHLNewaResults(res));
            });
    };
}

Api.getCurrentNHLNews() basically here you will make network request to fetch news lists or whatever. You may need to create different functions to make diff api requests.

Now you need to connect to the component via store Below code is just for illustration -

import { getCurrentNHLNews }  from '../../actions/news-actions';

// Other code related to Component

// Now you can call getCurrentNHLNews to dispatch async action
  <NavItem onClick={this.props.getCurrentNHLNews} eventKey={1}>NFL</NavItem>


LinkContainer.propTypes = {
    getCurrentNHLNews : PropTypes.func.isRequired
}

export default connect(null , { getCurrentNHLNews })(LinkContainer);

Instead of passing null as first parameter you may want to subscribe to some state part as per your need.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the answer.But i still have a problem . I added your changes and my getCurrentNHLNews function looks like export function getCurrentNHLNews() { return dispatch => { return getNewsJSON() .then(res => { dispatch(setCurrentNews(res)); }); }; } But i keep getting The prop getCurrentNHLNews` is marked as required in MainNav, but its value is undefined.` and the function is not getting called.
import { getCurrentNHLNews } from 'actions/news-actions'; did you implement above import? Just check the path is correct or not.
Yes I did import and I did check that the function gets imported properly. But I still get the warning.
have you installed "redux-thunk" npm module?
Yes. I have my index.jsx has the following code const store = createStore( reducer, applyMiddleware(thunk) );
|

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.