I'm very new to react and don't understand quite all of the restrictions yet. I'm trying to do a simple page switch after a button is clicked. After researching I figured useNavigate() would be used best for this situation. After trying to implement it into my code I realized what I had, did absolutely nothing. My goal is to send the user to a home page once the register button is clicked. As of right now, when I click the button nothing happens. This could be some small detail I missed or just me being completely oblivious. Please let me know if you think you see anything of importance, thanks in advance.
Here is my apps main page with my path being src/components/login/register:
import React from "react";
import "react-datepicker/dist/react-datepicker.css";
import { useNavigate } from "react-router-dom";
import axios from 'axios';
const api = axios.create({
...
})
const sendDetailsToServer = (payload) => {
...
}
const GoToLogin = () => {
let navigate = useNavigate();
navigate('/home');
}
export class Register extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.onInputchange = this.onInputchange.bind(this);
this.onSubmitForm = this.onSubmitForm.bind(this);
}
onInputchange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
onSubmitForm() {
let registerInfo = {
user_name : this.state.username,
password : this.state.password,
email_id : this.state.email
}
sendDetailsToServer(registerInfo);
GoToLogin();
}
render() {
return (
<div className="base-container" ref={this.props.containerRef}>
<h1>Welcome!</h1>
<link rel="stylesheet" href="" />
<div className="header">Please Enter Your Account Information</div>
<div className="content">
...
<div className="footer">
<button type="button" className="btn" onClick={this.onSubmitForm}>
Register
</button>
</div>
<div className="footer-fill"></div>
</div>
);
}
}
Here is my home page found under my path src/components/login/home:
import React from "react";
const Home = () => {
return(
<div>
<h1>Login</h1>
</div>
);
};
export default Home;
useNavigate hook is added to version 6, and it can be used only in functional component. If you want to use it in class component, create a HOC(withRouter).
import { useNavigate } from "react-router-dom";
export const withRouter = (Component) => {
const Wrapper = (props) => {
const navigate = useNavigate();
return <Component navigate={navigate} {...props} />;
};
return Wrapper;
};
and use it in your register.js like this
export default withRouter(Register)
here is the complete code.
import React from "react";
import "react-datepicker/dist/react-datepicker.css";
import axios from 'axios';
const api = axios.create({
...
})
const sendDetailsToServer = (payload) => {
...
}
class Register extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.onInputchange = this.onInputchange.bind(this);
this.onSubmitForm = this.onSubmitForm.bind(this);
}
onInputchange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
onSubmitForm() {
let registerInfo = {
user_name : this.state.username,
password : this.state.password,
email_id : this.state.email
}
sendDetailsToServer(registerInfo);
this.props.navigate('/home');
}
render() {
return (
<div className="base-container" ref={this.props.containerRef}>
<h1>Welcome!</h1>
<link rel="stylesheet" href="" />
<div className="header">Please Enter Your Account Information</div>
<div className="content">
...
<div className="footer">
<button type="button" className="btn" onClick={this.onSubmitForm}>
Register
</button>
</div>
<div className="footer-fill"></div>
</div>
);
}
}
export default withRouter(Register)
sample code
Related
The issue
I am trying to use Context to pass GitHub API authorised user data from the login page the the home page so that the user information can be displayed (avatar image, name etc.)
However whenever I try to access the context from my class component Home in Home.js I am told Cannot access 'AuthContext' before initialization.
My Code
Login.js
import React, { useState, useEffect, useContext } from "react";
import { Redirect } from "react-router-dom";
import Styled from "styled-components";
import { AuthContext } from "../App";
export default function Login() {
const { state, dispatch } = useContext(AuthContext);
const [data, setData] = useState({ errorMessage: "", isLoading: false });
const { client_id, redirect_uri } = state;
useEffect(() => {
const url = window.location.href;
const hasCode = url.includes("?code=");
if (hasCode) {
const newUrl = url.split("?code=");
window.history.pushState({}, null, newUrl[0]);
setData({ ...data, isLoading: true });
const requestData = {
code: newUrl[1]
};
const proxy_url = state.proxy_url;
fetch(proxy_url, {
method: "POST",
body: JSON.stringify(requestData)
})
.then(response => response.json())
.then(data => {
dispatch({
type: "LOGIN",
payload: { user: data, isLoggedIn: true }
});
})
.catch(error => {
setData({
isLoading: false,
errorMessage: "Sorry! Login failed: " + error
});
});
}
}, [state, dispatch, data]);
if (state.isLoggedIn) {
return <Redirect to="/" />;
}
return (
<Wrapper>
<section className="container">
<div className="card">
<span className="errorMessage">{data.errorMessage}</span>
<div className="login-container">
{data.isLoading ? (
<div className="loader-container">
<div className="loader"></div>
</div>
) : (
<>
{
}
<a
className="login-link"
href={`https://github.com/login/oauth/authorize?scope=user&client_id=${client_id}&redirect_uri=${redirect_uri}`}
onClick={() => {
setData({ ...data, errorMessage: "" });
}}
>
<span className="btn">Login with GitHub</span>
</a>
</>
)}
</div>
</div>
</section>
</Wrapper>
);
}
const Wrapper = Styled.section`
.container {
background-color: #333;
}
`;
Home.js
import React from "react";
import { Redirect } from "react-router-dom";
import Styled from "styled-components";
import { AuthContext } from "../App";
class Home extends React.Component {
constructor() {
super()
this.state = {
'items': []
}
}
render() {
const { state, dispatch } = this.context
if (!state.isLoggedIn) {
return <Redirect to="/login" />;
}
const { avatar_url, name, public_repos, followers, following } = state.user
const handleLogout = () => {
dispatch({
type: "LOGOUT"
});
}
return (
<Wrapper>
<div className="container">
<div>
<div className="profileBox">
<button className="btn" onClick={()=> handleLogout()}>Logout</button>
<img className="avatarImage" src={avatar_url} alt="Avatar"/>
<span>{name}</span>
</div>
</div>
</div>
</Wrapper>
)
}
}
const Wrapper = Styled.section`
.content {
background-color: lightgray;
}
`;
Home.contextType = AuthContext
export default Home
app.js
import React, { createContext, useReducer } from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Home from "./components/Home";
import Login from "./components/Login";
import { initialState, reducer } from "./store/reducer";
import Styled from "styled-components";
export const AuthContext = createContext();
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<AuthContext.Provider
value={{
state,
dispatch
}}
>
<Router>
<Switch>
<Route path="/login" component={Login}/>
<Route path="/" component={Home}/>
</Switch>
</Router>
</AuthContext.Provider>
);
}
export default App;
What I have tried
I have attempted to move the Home.contextType = AuthContext into the render() however becuase the render is called twice (I think it is related to this) on the first run it is an empty object, state and dispatch are not there. This leads to errors relating to isLoggedIn and other context related items being "undefined" so I did not think this would be the appropriate solution.
I have also tried using statis contextType = AuthContext both before the constructor declaration and after but neither of these worked for me.
I have also attempted to use AuthContext.Consumer but with no avail as when this we put in place within the render() I was then not able to access any other the data. But then I am happy to admit React is new to me and therefore I may have misunderstood how Consumer works.
Any help is greatly appreciated.
I am trying to make a movie search function using React, Axios, and movieDB API. The functionality I am trying to implement right now is typing in a movie into the search bar and clicking the submit button will return the movie title as an H1 element.
My onClick function does not work: <button onClick={(e)=>clickHandler()}>submit</button>
componentDidMount() will work only when the page refreshes and you cannot search for anything as the submit button is broken.
I am not sure how to implement this, but I would also not mind if I could get it to search by hitting enter instead of using a button, whichever is easier.
Here is my code so far.
App.js
import React from "react"
import Movielist from './components/Movielist'
function App() {
return (
<div>
<input type="search" id="search" />
<button onClick={(e)=>clickHandler()}>submit</button>
<h1 id="title">title</h1>
<Movielist />
</div>
)
}
export default App
Movielist.js
import React from 'react';
import axios from 'axios';
export default class Movielist extends React.Component {
state = {
title: ""
}
componentDidMount() {
const API_KEY = '***********************';
const query = document.getElementById('search').value;
axios.get(`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&query=${query}`)
.then(res => {
const title = res.data['results'][0]['title'];
this.setState({ title });
})
}
render() {
return (
<h1>{this.state.title}</h1>
)
}
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
import React from 'react';
import axios from 'axios';
export default class Movielist extends React.Component {
state = {
title: ""
}
clickHandler = (event) => {
if (event.keyCode === 13) {
const query = event.target.value;
const API_KEY = '***********************';
axios.get(`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&query=${query}`)
.then(res => {
const title = res.data['results'][0]['title'];
this.setState({ title });
})
}
}
render() {
return (
<input type="search" id="search" onKeyDown={event => this.clickHandler(event)} />
<h1>{this.state.title}</h1>
)
}
}
You should call API to get the movie list after hitting the button, then pass the data that you've got to Movielist. Try this:
In App.js:
import React from "react"
import axios from 'axios'
import Movielist from './components/Movielist'
function App() {
const [movieList, setMovieList] = React.useState([])
const handleOnSubmit = () => {
const API_KEY = '***********************';
const query = document.getElementById('search').value;
axios.get(`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&query=${query}`)
.then(res => {
const title = res.data['results'][0]['title'];
setMovieList(res.data['results'])
})
}
return (
<div>
<input type="search" id="search" />
<button onClick={handleOnSubmit}>submit</button>
<h1 id="title">title</h1>
<Movielist movieList={movieList}/>
</div>
)
}
export default App
In Movielist.js:
import React from 'react';
const Movielist = ({movieList}) => {
return (
<div>
{
movieList.map(movie => <h1 key={movie.key}>{movie.title}</h1>)
}
<div/>
)
}
}
export default Movielist
import React, {useState} from "react"
import axios from 'axios';
import Movielist from './components/Movielist'
const [title, setTitle] = useState("")
const API_KEY = '***********************'
function App() {
const clickHandler = () => {
const query = document.getElementById('search').value;
axios.get(`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&query=${query}`)
.then(res => {
const title = res.data['results'][0]['title'];
setTitle(title);
})
}
return (
<div>
<input type="search" id="search" />
<button onClick={clickHandler}>submit</button>
<h1 id="title">title</h1>
<Movielist title={title} />
</div>
)
}
export default App
just move call api handle to your onclik func then pass title props to movie list
If you want to query the API after user push submit button. You should put your call to API in the call handler, then pass the state from App to MovieList as props
export class App extends React.Component {
state = {
title: ""
}
clickHandler() {
const API_KEY = '***********************';
const query = document.getElementById('search').value;
axios.get(`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&query=${query}`).then(res => {
const title = res.data['results'][0]['title'];
this.setState({ title });
});
}
render() {
return (
<div>
<input type="search" id="search" />
<button onClick={(e)=>clickHandler()}>submit</button>
<h1 id="title">title</h1>
<Movielist list={this.state.title}/>
</div>
)
}
}
export class MovieList extends React.Component {
render() {
<h1>{this.props.title}</h1>
}
}
Alternatively, you can wrap the input in a element and use onSubmit + evt.preventDefault() instead, by doing so you can handle button click and pressing "Enter" to submit.
I learn React Redux and have some issues.
In the code below I do mapStateToProps to listen for changes and I use the mapDispatchToProps to send a notification. When there is a change in the Store I send a Notification. In order for this to work I have to put this Helper in the App.jsx render() method even do this Helper Component code below does not add anything to the App.jsx. I learn React and wonder how I can change this Notefication.js so it listen for mapStateToProps and can do mapDispatchToProps without adding it to App.jsx render().
It just feels so unnecessary to have to add this Component to the App.jsx render only to get the mapStateToProps mapDispatchToProps working?
Notefication.js
import { connect } from "react-redux";
import 'react-redux-notify/dist/ReactReduxNotify.css';
import { createNotification, NOTIFICATION_TYPE_SUCCESS } from 'react-redux-notify';
import { Notify } from 'react-redux-notify';
import React, { Component } from "react";
const mySuccessNotification = {
message: 'You have been logged in!',
type: NOTIFICATION_TYPE_SUCCESS,
duration: 0,
canDismiss: true,
icon: <i className="fa fa-check" />
}
class Helper extends Component {
senNotification() {
const { createNotification } = this.props;
createNotification(mySuccessNotification);
}
render() {
return (
<div>
<Notify />
{this.senNotification()}
</div>
)
}
}
const mapDispatchToProps = dispatch => ({
createNotification: (config) => {
dispatch(createNotification(config))
},
})
const mapStateToProps = state => {
return { badword: state.rootReducer.badword };
};
export default connect(mapStateToProps, mapDispatchToProps)(Helper)
App.jsx
import React, { Component } from "react";
import List from "./List.jsx";
import Form from "./Form.jsx";
import Helper from "../components/Notification";
class App extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
const { addToast } = this.props.actions;
addToast({ text: "Hello, World!" });
}
render() {
return (
<main>
<div className="row mt-5">
<div className="col-md-4 offset-md-1">
<h2>Articles</h2>
<List />
</div>
<div className="col-md-4 offset-md-1">
<h2>Add a new article</h2>
<Form />
</div>
</div>
<Helper/>
</main>
);
}
}
export default App;
React only renders new, if the component values changes. So if the reducer is connected and you load some values which changes, the component renders and the function will be triggered.
I would not trigger the function this.senNotification in the render function I would prefer to use componentDidUpdate to trigger the function.
import { connect } from "react-redux";
import 'react-redux-notify/dist/ReactReduxNotify.css';
import { createNotification, NOTIFICATION_TYPE_SUCCESS } from 'react-redux-notify';
import { Notify } from 'react-redux-notify';
import React, { Component } from "react";
const mySuccessNotification = {
message: 'You have been logged in!',
type: NOTIFICATION_TYPE_SUCCESS,
duration: 0,
canDismiss: true,
icon: <i className="fa fa-check" />
}
class Helper extends Component {
componentDidUpdate (prevProps) {
const { createNotification, badword } = this.props
if(prevProps.badword !== badword) {
this.senNotification()
}
}
senNotification() {
const { createNotification } = this.props;
createNotification(mySuccessNotification);
}
render() {
return <Notify />
}
....
}
I'm new to react + redux. I encountered a problem which my app is not re-render when I dispatch an action. However, I use getState() to examine the state, it did change. I look up documents but still have no idea what the problem is. Please help me, thanks.
The code is as below
====actions.js====
export const ADD_MAIL = 'ADD_MAIL';
export const DEL_MAIL = 'DEL_MAIL';
export function addMail(email) {
return {
type: ADD_MAIL,
email
}
}
export function delMail(id) {
return {
type: DEL_MAIL,
id
}
}
====reducers.js====
import { combineReducers } from 'redux'
import { ADD_MAIL, DEL_MAIL } from '../actions/actions'
import MAILS from '../data'
function emails(state = MAILS, action) {
switch (action.type) {
case ADD_MAIL:
console.log("ADD_MAIL");
return [
action.email,
...state
];
case DEL_MAIL:
let idx = state.length;
let i = 0;
// Find the target mail
while(idx--) {
if (state[idx] && state[idx].serialNo === action.id)
i = idx;
}
let arr1 = state.slice(0, i);
let arr2 = state.slice(i + 1);
let newList = arr1.concat(arr2);
console.log("DEL_MAIL");
return newList;
default:
return state;
}
}
const rootReducer = combineReducers({
emails
});
export default rootReducer;
====main.js====
import React from 'react'
import { render } from 'react-dom'
import { Link } from 'react-router'
import { connect } from 'react-redux'
import { createStore } from 'redux'
import { addMail, delMail } from './actions/actions'
import rootReducer from './reducers/reducers'
import * as btn from './module/button'
import * as module from './module/module'
var store = createStore(rootReducer);
class Inbox extends React.Component {
constructor(props) {
super(props);
this.state = {
searchText: ''
}
this.handleUserInput = this.handleUserInput.bind(this);
this.deleteMail = this.deleteMail.bind(this);
this.sendMail = this.sendMail.bind(this);
}
handleUserInput(searchText) {
this.setState({
searchText: searchText
});
}
deleteMail(obj) {
store.dispatch(delMail(obj.serialNo));
console.log(store.getState());
// This displays the correct new state in console after dispatch
}
sendMail(newMail) {
store.dispatch(addMail(newMail));
console.log(store.getState());
// This displays the correct new state in console after dispatch
}
render() {
let mails = [];
let search = this.state.searchText.toUpperCase();
let emails = this.props.emails;
emails.map(mail => {
if (mail.from.toUpperCase().indexOf(search) !== -1)
mails.push(mail);
});
let sender = (mails.length === emails.length) ? "all" : this.state.searchText;
return (
<div className="main">
<div className="toolbar">
<span>You have {mails.length} message from {sender}.</span>
<module.SearchInput searchText={this.state.searchText} onUserInput={this.handleUserInput} />
<div className="functions">
<btn.AddButton />
</div>
</div>
<div className="mailList">
{mails.map(mail => (
<div className="item" key={mail.serialNo}>
<div className="info sender">
From: {mail.from}
</div>
<div className="info date">
{mail.date}
</div>
<div className="info subject">
Subject: {mail.subject}
</div>
<div className="functions">
<btn.ReadButton serialNo={mail.serialNo} />
<btn.DeleteButton serialNo={mail.serialNo} deleteMail={this.deleteMail} />
</div>
</div>
))}
</div>
<module.NewMailInput sendMail={this.sendMail} />
</div>
);
}
}
function mapStateToProps(state) {
return {
emails: state.emails
};
}
export default connect(mapStateToProps)(Inbox);
====app.js====
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import { Menu } from './menu'
import { Mail } from './main'
import Inbox from './main'
import rootReducer from './reducers/reducers'
var store = createStore(rootReducer);
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div style={{height: '100%'}}>
<Menu />
{this.props.children}
</div>
);
}
}
class Home extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Inbox />
);
}
}
render(
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home} />
<Route path="/inbox" component={Inbox} />
<Route path="/message/:mailSerial" component={Mail} />
</Route>
</Router>
</Provider>,
document.getElementById('app-container'))
Try this:
import React from 'react'
import { render } from 'react-dom'
import { Link } from 'react-router'
import { connect } from 'react-redux'
import { addMail, delMail } from './actions/actions'
import * as btn from './module/button'
import * as module from './module/module'
class Inbox extends React.Component {
constructor(props) {
super(props);
this.state = {
searchText: ''
}
this.handleUserInput = this.handleUserInput.bind(this);
this.deleteMail = this.deleteMail.bind(this);
this.sendMail = this.sendMail.bind(this);
}
handleUserInput(searchText) {
this.setState({
searchText: searchText
});
}
deleteMail(obj) {
this.props.delMail(obj.serialNo); //Call the delMail action
console.log(store.getState());
}
sendMail(newMail) {
this.props.addMail(newMail); //Call the addMail action
console.log(store.getState());
}
render() {
let mails = [];
let search = this.state.searchText.toUpperCase();
let emails = this.props.emails;
emails.map(mail => {
if (mail.from.toUpperCase().indexOf(search) !== -1)
mails.push(mail);
});
let sender = (mails.length === emails.length) ? "all" : this.state.searchText;
return (
<div className="main">
<div className="toolbar">
<span>You have {mails.length} message from {sender}.</span>
<module.SearchInput searchText={this.state.searchText} onUserInput={this.handleUserInput} />
<div className="functions">
<btn.AddButton />
</div>
</div>
<div className="mailList">
{
mails.map(mail => (
<div className="item" key={mail.serialNo}>
<div className="info sender">From: {mail.from}</div>
<div className="info date">{mail.date}</div>
<div className="info subject">Subject: {mail.subject}</div>
<div className="functions">
<btn.ReadButton serialNo={mail.serialNo} />
<btn.DeleteButton serialNo={mail.serialNo} deleteMail={this.deleteMail} />
</div>
</div>
))
}
</div>
<module.NewMailInput sendMail={this.sendMail} />
</div>
);
}
}
function mapStateToProps(state) {
return {
emails: state.emails
};
}
//Connect the component to re-render when state change and
// makes the emails and actions to be available through this.props
export default connect(mapStateToProps, {delMail, addMail})(Inbox);
//To connect Mail component which I suppose that is in another file
function mapStateToProps(state) {
return { emails: state.emails };
}
export default connect(mapStateToProps, {})(Mail);
In your main.js file, you have made a Inbox component. That is a React Component but not a Redux Component.
You have to do something like this while exporting Inbox component.
module.exports = connect((store)=> {
return {emails: store.emails}
})(Inbox)
You have 2x stores: one in main.js and one in app.js. Remove the one in main.js and update the calls to dispatch to use the one passed as props:
class Inbox extends React.Component {
...
deleteMail(obj) {
this.props.dispatch(delMail(obj.serialNo));
}
...
}
having a serious challenge with my React/Redux authorization setup and I'm at a loss. Current error is:
HomeHeader.js?8595:26 Uncaught ReferenceError: dispatch is not defined
There's a lot wrong here, and any help would be appreciated.
I'm creating two authorization components, one to register and one to login. The AuthorizationLogin component is what I'm working on first.
I don't know how to get this to pass the event info it grabs form the form fields, put in the variable creds, and then on up through the HomeHeader component, and then again up to the HomePage container. Do I put all of the authorization components into one enormous HomeHeader component?
Here's the main code and flow. Code isn't loading right into StackOverflow for some reason.
HomePage.js
import React from 'react';
import {connect} from 'react-redux';
import * as actions from '../../../actions/homeEventFormActions';
import HomeHeader from '../homeHeader/HomeHeader';
import HomeEventForm from '../homeEventForm/HomeEventForm';
class HomePage extends React.Component {
constructor(props) {
super(props);
}
render() {
const { dispatch } = this.props;
return (
<div>
< HomeHeader />
< HomeEventForm
onSubmit={this.props.onSubmit}
/>
</div>
);
}
}
function mapStateToProps(state) {
return {
homeEventForm: state.homeEventForm
};
}
function mapDispatchToProps(dispatch) {
return {
onSubmit: (eventName) => dispatch(actions.createEventButton(eventName)),
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(HomePage);
HomeHeader.js
import React, { Component, PropTypes } from 'react';
import AuthorizeLogin from '../../Authorization/AuthorizeLogin';
import AuthorizeRegister from '../../Authorization/AuthorizeRegister';
import { loginUser } from '../../../actions/authorizationActions';
class HomeHeader extends React.Component {
constructor() {
super();
}
_handleChange(eventKey) {
...
<AuthorizeLogin
onLoginClick={ (creds) => dispatch(loginUser(creds))}
/>
...
}
return;
}
render() {
const { dispatch } = this.props;
return (
...
<Modal.Header closeButton onClick={ ()=> this._handleChange(5)}>
...
);
}
}
export default HomeHeader;
AuthorizeLogin.js
import React from 'react';
class AuthorizeLogin extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {};
this._login = this._login.bind(this);
}
_login(e) {
e.preventDefault;
const email = this.refs.email;
const password = this.refs.password;
const creds = { email: email.value.trim(), password: password.value.trim() };
this.props.onLoginClick(creds);
}
render() {
return (
<Form horizontal onSubmit={this._login}>
<h4 className="authEmailText">Login with your email</h4>
<input type="email" placeholder="urawesome#example.com" ref='email' />
<input type="password" placeholder="Password" ref='password' />
</Form>
);
}
}
export default AuthorizeLogin;
All the actions should be dispatched from container. In this case, the container should have the dispatch.
function mapDispatchToProps(dispatch) {
return {
onSubmit: (eventName) => dispatch(actions.createEventButton(eventName)),
onLogin: (creds) => dispatch(loginUser(creds)),
};
}
The onLogin should be passed to downstream components via props:
<HomeHeader onLogin={this.props.onLogin} />
<AuthorizeLogin
onLoginClick={this.props.onLogin}
/>