React-Redux Application: 'props' is not defined' - reactjs

I am creating a React-Redux application. Before adding the content above render(), props was defined. However, after I started adding said content, the app began having problems reading the variable. I don't know what happened.
Could somebody please help me understand why props isn't being recognized anymore? I'd really appreciate it.
Login.js
import React from 'react';
import Modal from 'react-bootstrap/Modal';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import './login.css';
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: ''
}
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value});
}
render() {
return (
<>
<Modal show={props.modalOpen} onHide={props.handleModalOpen}>
<Modal.Header closeButton>
<Modal.Title>Login</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group>
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
name="username"
className="form-control"
/>
</Form.Group>
<Form.Group>
<Form.Label>Password</Form.Label>
<Form.Control
type="text"
name="password"
className="form-control"
/>
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="danger" type="submit" onClick={props.handleModalOpen}>
Submit
</Button>
<Button variant="primary" onClick={props.handleClose}>
Cancel
</Button>
</Modal.Footer>
</Modal>
</>
);
}
}
export default LoginForm;
Navbar.js
import React from "react";
import { Link } from 'react-router-dom';
import './navbar.css';
import LoginForm from '../LoginForm/login.js';
// import SignUpModal from '../SignUpModal/signup.js';
class Navbar extends React.Component {
state = {
modalOpen: false
}
handleModalOpen = () => {
this.setState((prevState) => {
return {
modalOpen: !prevState.modalOpen
}
})
}
render() {
return (
<div>
<nav className="navbar navbar-expand-sm navbar-dark px-sm-5">
<div className="container">
<Link to='/'>
<div className="navbar-brand">
<i class="fas fa-globe fa-2x"></i>
</div>
</Link>
<ul className="navbar-nav align-items-right">
<li className="nav-item ml-5">
<a onClick={this.handleModalOpen} className="nav-link">
Login
</a>
</li>
<li className="nav-item ml-5">
<a onClick={this.handleModalOpen} className="nav-link">
Sign Up
</a>
</li>
</ul>
</div>
</nav>
<LoginForm
modalOpen={this.state.modalOpen}
handleModalOpen={this.handleModalOpen}
/>
{/* <SignUpModal
modalOpen={this.state.modalOpen}
handleModalOpen={this.handleModalOpen}
/> */}
</div>
)
}
}
export default Navbar;

In your Login.js, it's written using class-based syntax, hence it has to be this.props instead of props
<Modal show={this.props.modalOpen} onHide={this.props.handleModalOpen}>
Alternatively, Login.js can be rewrite into functional-based component, you can then use props like below
const Login = props => {
return (
<Modal show={props.modalOpen} onHide={props.handleModalOpen} />
)
}

Related

After click button or Enter, the input value should be return empty but it it didn't return empty

First of all, thank you so much for trying to help me out! I am just getting started learning React.js, so If I ask a little stupid question, I am sorry. What I expect that when I click the "Post" button, it should be added the list above and the input value should be return "empty" but it remains what I write in the input. I declared the empty value here!
addComment = () => {
this.setState({
commentList: this.state.commentList.concat([this.state.value]),
value: '',
});
};
<ul className="feed-comments">
<Comment commentAddList={this.state.commentList} />
</ul>
but it didn't return empty input value. I will leave the whole code below!
Feed.js
import React, { Component } from 'react';
// import "../../styles/common.scss";
import './Feed.scss';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import {
faHeart,
faComment,
faPaperPlane,
faBookmark,
faEllipsisH,
} from '#fortawesome/free-solid-svg-icons';
import Comment from '../../../compoonents/Comment/Comment';
class Feed extends Component {
constructor() {
super();
this.state = {
value: '',
commentList: [],
};
}
getValue = event => {
this.setState({
value: event.target.value,
});
};
addComment = () => {
this.setState({
commentList: this.state.commentList.concat([this.state.value]),
value: '',
});
};
addCommEnter = e => {
if (e.key === 'Enter') {
this.addComment();
}
};
render() {
return (
<div className="feeds">
<div className="article">
<div className="identi">
<img className="selfi-identi" alt="selfi-img" src="about.png" />
<span className="name"> Jiwan Jeon </span>
{/* <i id="test" class="fa fa-ellipsis-h" aria-hidden="true"></i> */}
<div className="faEllipsisH">
<FontAwesomeIcon icon={faEllipsisH} />
</div>
</div>
<div className="pic">
<img id="feed-pic" src="ucscPic.png" />
</div>
<div className="show-box">
<div className="reaction-icons">
<FontAwesomeIcon icon={faHeart} className="heart" />
<FontAwesomeIcon icon={faComment} className="comment" />
<FontAwesomeIcon icon={faPaperPlane} className="plane" />
<FontAwesomeIcon icon={faBookmark} className="bookMark" />
</div>
<div className="like-counts">
<span>like 4,000</span>
</div>
<div className="check-comments">
<span>
UC Santa Cruz will continue to offer most courses remotely or
online for spring and summer 2021, providing in-person
instruction for a small
</span>
<a id="space" href="">
expanding
</a>
<br />
Check the all comments
<ul className="feed-comments">
<Comment commentAddList={this.state.commentList} />
</ul>
</div>
</div>
<div className="comment">
<i className="fa fa-smile-o" />
<input
// onChange={this.textChange}
// onKeyPress={this.enterClick}
onKeyPress={this.addCommEnter}
onChange={this.getValue}
className="user-input"
type="text"
placeholder="Add Comment..."
/>
<button onClick={this.addComment} className="post">
Post
</button>
</div>
</div>
</div>
);
}
}
export default Feed;
This is Comment.js
import React, { Component } from 'react';
export class Comment extends Component {
render() {
return (
<>
{this.props.commentAddList.map((comm, idx) => {
return <li key={idx}>{comm}</li>;
})}
</>
);
}
}
export default Comment;
Your input field is missing the value property which should be bound to the state in order to have a controlled input field. You should add value={this.state.value} as follow:
<input
// onChange={this.textChange}
// onKeyPress={this.enterClick}
onKeyPress={this.addCommEnter}
onChange={this.getValue}
className="user-input"
type="text"
placeholder="Add Comment..."
value={this.state.value}
/>
You can learn more about "Controlled Components" in this section of the documentation.

How to manage the state using Redux

I'm working on a project, I'm using Django as backend, React as frontend and Redux as state manager. I want to pass a function from my login and register component to my Header component, whereas my header component is not a root component I can't pass params directly to other components. I know redux can solve this problem but I don't know how?
I have two separate links in my header component (Login, Register), I mean when I click on login it should call the openLoginModal() from my login component and the same process for register component
My header component
import React, { Component, Fragment } from "react";
import { Link } from "react-router-dom";
export class Header extends Component {
render() {
return (
<Fragment>
<nav className="navbar navbar-expand-sm ">
<div className="container">
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarTogglerDemo01"
aria-controls="navbarTogglerDemo01"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarTogglerDemo01">
<a className="navbar-brand" href="/">
Todos
</a>
<ul className="navbar-nav ml-auto mt-2 mt-lg-0">
<Link to="/register">
<button className="btn btn-outline-primary btn-sm mx-2">
Register
</button>
</Link>
<Link to="/login">
<button className="btn btn-outline-primary btn-sm">
Login
</button>
</Link>
</ul>
</div>
</div>
</nav>
</Fragment>
);
}
}
export default Header;
I also used react-awesome-modal for creating login and register modal, here is my login component
import React, { Component, Fragment } from "react";
export class Login extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
username: "",
password: "",
};
}
openLoginModal() {
this.setState({
visible: true,
});
}
closeLoginModal() {
this.setState({
visible: false,
});
}
render() {
const { username, password } = this.state;
return (
<Fragment>
<section>
<Modal
visible={this.state.visible}
width="400"
height="300"
effect="fadeInUp"
onClickAway={() => this.closeLoginModal()}
>
<div>
<form>
<div className="form-group">
<label>Username</label>
<input
type="text"
className="form-control"
name="username"
value={username}
/>
</div>
<div className="form-group">
<label>Password</label>
<input
type="password"
className="form-control"
name="password"
value={password}
/>
</div>
<div className="form-group">
<button className="btn btn-primary btn-sm my-2">Login</button>
</div>
</form>
</div>
</Modal>
</section>
</Fragment>
);
}
}
export default Login;
Just only store variable isOpenModal into the state of redux and add 2 action creator
openModal() {
return { type: 'OPEN_MODAL' }
}
closeModal {
return { type: 'CLOSE_MODAL'
}
change state through reducers (file reducers)
// another code
switch(action.type) {
case 'OPEN_MODAL':
state.isOpenModal = true;
break;
case 'CLOSE_MODAL':
state.isOpenModal = false;
break;
// another code
}
In file Header use mapDispatchToProps to call 2 action creator openModal and closeModal as created above.
In file Login use mapStateToProps to use state isOpenModal in state of redux.

how to redirect back to App with React.js from a component?

i'm new learner of React.js and i don't finding the right solution.
i have the CreateUser component and when a client success at creating one i want to Redirect the client to App...
i need it to happend in this function of CreateUser Component
private handleSubmit(e:any){
e.preventDefault();
this.setState({
username: this.state.username,
password: this.state.password,
confirmPassword: this.state.confirmPassword,
userEmail: this.state.userEmail
})
this.passConfrim();
if (this.isAlertVisible){
console.log(this.state)
this.myUserDateService.create(this.state);
----> ** Right Here i need to redirect! ** <----
}
}
in the end of the function at the if statement
App:
import './App.css';
import { LoginComponent } from './components/LoginComponent';
import CreateUser from './components/CreateUser';
import "bootstrap/dist/css/bootstrap.min.css";
import { Router, Switch, Route, Link, useHistory as history} from "react-router-dom";
function App() {
return (
<Router history={history()} >
<nav className="navbar navbar-expand navbar-dark bg-dark">
<a href="/Home" className="navbar-brand">
To Do List
</a>
<div className="navbar-nav mr-auto">
<li className="nav-item">
<Link to={"/Login"} className="nav-link">
Login
</Link>
</li>
<li className="nav-item">
<Link to={"/CreateUser"} className="nav-link">
Create User
</Link>
</li>
</div>
</nav>
<div id="App-content">
<Switch >
<Route exact path={["/", "/Home"]} />
<Route path="/Login" exact component={LoginComponent} />
<Route path="/CreateUser" exact component={CreateUser} />
</Switch>
</div>
</Router>
);
}
export default App;
CreateUser Component:
import React, { Component } from 'react';
import { UserDataService } from '../services/UserData.service';
interface IState {
username:string;
userEmail:string;
password:string;
confirmPassword:string;
}
export class CreateUser extends Component <{}, IState> {
isAlertVisible: boolean = true;
myUserDateService = new UserDataService();
constructor(props: {}, myUserDateService:UserDataService){
super(props );
this.state = {
username:"",
password:"",
confirmPassword:"",
userEmail:"",
}
}
private handleSubmit(e:any){
e.preventDefault();
this.setState({
username: this.state.username,
password: this.state.password,
confirmPassword: this.state.confirmPassword,
userEmail: this.state.userEmail
})
this.passConfrim();
if (this.isAlertVisible){
console.log(this.state)
this.myUserDateService.create(this.state);
}
}
passConfrim(){
if(this.state.password !== this.state.confirmPassword){
this.isAlertVisible = false;
}else{
this.isAlertVisible = true;
}
}
render() {
return (
<div className="form-group">
<h1>Create User</h1>
<form onSubmit={e => this.handleSubmit(e)}>
<label >Username</label>
<input className="form-control" type="text" placeholder='Enter Username...' onChange={e => this.setState({username : e.target.value})} required/>
<br/>
<label >Email</label>
<input className="form-control" type="text" placeholder='Enter your email...' onChange={e => this.setState({userEmail : e.target.value})} required/>
<br/>
<label >Passowrd</label>
<input className="form-control" type="password" placeholder='Enter Password...' onChange={e => this.setState({password : e.target.value})} required/>
<br/>
<label >Confirm Passowrd</label>
<input className="form-control" type="password" placeholder='Confirm Password...' onChange={e => this.setState({confirmPassword : e.target.value })} required />
<div style={{color: "red", textAlign: "left"}} hidden={this.isAlertVisible}>**password not match</div>
<br/>
<button className="btn btn-primary" type="submit" >Create User</button>
</form >
</div>
)
}
}
export default CreateUser;
Basically you need not pass history with Router instead you can use withRouter high order component from react-router.
Import withRouter inside createUser component - https://reacttraining.com/react-router/core/api/withRouter
import { withRouter } from "react-router";
Then we just need to export CreateUser component like -
export default withRouter(CreateUser);
Now you have access to all props related to routing inside CreateUser component, now you can use -
this.props.history.push('/your-route');
To check what else properties you have with withRouter, you can just console.log this.props.history inside CreateUser component.
Tip - You cannot use hooks inside class components, so you cannot use useHistory inside CreateUser component instead use withRouter.
you can use history.push('/yourRoute') and that will take you to whatever route your heart so desires
Since you are extending the user component from react, it is a class component and you cannot use 'useHistory' hooks inside it.
Also you are passing history as a prop to router, can you try the below code to navigate and let me know.
this.props.history.push('/yourroute');

ReactJS: Cannot read property 'bind' of undefined

I'm tried to figure out How can I have these two buttons the Login and Sign up that will be toggling the Login and Sign up box back in forward.
I couldn't figure out.... Does anyone can solve this?
this is my code. I'd like to call "selected-controller" method from div item. But then, Cannot read property 'bind' of undefined.
Navigation.js
import React from 'react';
import { BrowserRouter as Router, Link } from 'react-router-dom';
import "../components/pages/Forms/MainScreen";
import Dropdown from "../components//pages/dropdowns/dropdowns";
import hamburger from "../images/menu.svg";
class Navigation extends React.Component {
constructor(props) {
super(props);
this.state = {
isExpanded: false
};
}
handleToggle(e) {
e.preventDefault();
this.setState(prevState => ({
isExpanded: !prevState.isExpanded, // negate the previous expanded state
}));
}
render() {
const { isExpanded } = this.state;
return (
<Router>
<div className="NavbarContainer">
<div className="mobilecontainer LeftNav">
<h2 className="BrandName LeftNav mobileboxmenu inline FarRight">Kommonplaces</h2>
<div className="hamburger inlinev" >
<img
onClick={e => this.handleToggle(e)}
alt="menubtn"
src={hamburger}
/>
</div>
</div>
<ul className={`NavBar collapsed ${isExpanded ? "is-expanded" : ""}`}>
<Dropdown/>
<li className="RightNav"><Link to="/">Host Your Space</Link></li>
<li className="RightNav"><Link to="/">About Us</Link></li>
<li className="RightNav"><Link to="/">Contact Us</Link></li>
<div className="btnflexright">
<div
className={"controller " + (this.state.isLoginOpen
? "selected-controller"
: "")}
onClick={this
.showLoginBox
.bind(this)}>
Login
</div>
<div
className={"controller " + (this.state.isRegisterOpen
? "selected-controller"
: "")}
onClick={this
.showRegisterBox
.bind(this)}>
Sign up
</div>
</div>
</ul>
</div>
</Router>
);
}
}
export default Navigation;
This is the main screen where the login and Sign form will go:
import React from 'react';
import RegisterBox from '../Forms/Register'
import LoginBox from '../Forms/Register'
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoginOpen: true,
isRegisterOpen: false
};
}
showLoginBox() {
this.setState({isLoginOpen: true, isRegisterOpen: false});
}
showRegisterBox() {
this.setState({isRegisterOpen: true, isLoginOpen: false});
}
render() {
return (
<div>
<div className="root-container">
{this.state.isLoginOpen && <LoginBox/>}
{this.state.isRegisterOpen && <RegisterBox/>}
</div>
</div>
)
}
}
export default App;
Login and Sign up Form are the same but in two different files Login.js and Register,js I will show the code for that one now.
//Login Box
import React from 'react';
class LoginBox extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<div className="formContent modal-main">
<h2>Welcome Back <span>Brandon!</span></h2>
<form>
<input
type="text"
name="email"
placeholder="Email Address"
/>
<input
name="password"
type="text"
placeholder="Password"
/>
<div className="passContent">
<div className="checkingPass">
<input
className="inline"
type="checkbox"
name="check"
value="Remember Password"
/>
<span
className="inline">
Remember Password
</span>
</div>
<p
className="passFont">
Forgot Password
</p>
</div>
<input
className="formmbtn"
type="button"
name="button"
alue="Login"
/>
<div
className="social-media-button">
<input
className="clearbtn"
type="button"
name="button"
value="Sign in with Facebook"
/>
<div
className="divider"
/>
<input
className="clearbtn"
type="button"
name="button"
value="Sign in with Facebook"
/>
</div>
<p
className="passFont">
Don't have an account?
<span>Sign up</span>
</p>
</form>
</div>
</div>
)
}
}
export default LoginBox;
The class Navigation doesn't have the functions showRegisterBox and showLoginBox, so this.showRegisterBox is undefined (that's why you get the Cannot read property 'bind' of undefined error when you do this.showRegisterBox.bind() on the Navigation Component.
Possible solutions:
If those functions aren't defined in the Navigation component, then you should probably pass them as props when you instantiate Navigation. That's the usual way a component communicates with it's parent component.
So if for example you were to use your Navigation component in App (which is where those functions are defined), you would do:
<Navigation showRegisterBox={this.showRegisterBox.bind(this)} showLoginBox={this.showLoginBox.bind(this)}/>
Then in Navigation you use them like such:
onClick={this.props.showRegisterBox}

I must add login to navbar in React

I must add login system to navbar, but when I login in anywhere, navbar does not appear. How can I solve it?
Navbar shows normally with no login system.
Navbar is on App.js.
authLinks - Section just for authenticated users (Dashboard and Log out buttons)
guestLinks - Section just for not-authenticated users (Login form in here)
My navbar + login:
import React, { Fragment, useState } from "react";
import { Link, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { logout } from "../../actions/auth";
import { login } from "../../actions/auth";
const Navbar = ({ auth: { isAuthenticated, loading }, login, logout }) => {
const [formData, setFormData] = useState({
email: "",
password: ""
});
const { email, password } = formData;
const onChange = e =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = async e => {
e.preventDefault();
login(email, password);
};
if (isAuthenticated) {
return <Redirect to="/dashboard" />;
}
const authLinks = (
<ul>
<li>
<Link to="/dashboard">
<i className="fas fa-user" /> <span className="hide-sm">Dashboard</span>
</Link>
</li>
<li>
<a onClick={logout} href="#!">
<i className="fas fa-sign-out-alt" />{" "}
<span className="hide-sm">Log out</span>
</a>
</li>
</ul>
);
const guestLinks = (
<form
className="form-inline my-2 my-lg-0 navbar-login"
onSubmit={e => onSubmit(e)}
>
<div className="form-group">
<input
className="form-control mr-sm-2"
type="email"
placeholder="Email Address"
name="email"
value={email}
onChange={e => onChange(e)}
/>
</div>
<div className="form-group">
<input
className="form-control mr-sm-2 my-sm-0"
type="password"
placeholder="Password"
name="password"
value={password}
onChange={e => onChange(e)}
/>
</div>
<input type="submit" className="btn btn-primary" value="Login" />
</form>
);
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<h1>
<Link className="navbar-brand" to="/">
<i className="fas fa-crown"></i>
<br />
nawdic
</Link>
</h1>
{!loading && (
<Fragment>{isAuthenticated ? authLinks : guestLinks}</Fragment>
)}
</nav>
);
};
Navbar.propTypes = {
logout: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
login: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool
};
const mapStateToProps = state => ({
auth: state.auth,
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { login, logout })(Navbar);
When user is logged in Navbar returns redirect component which is not the navbar itself
if (isAuthenticated) {
return <Redirect to="/dashboard" />;
}
Since isAuthenticated is passed to Navbar it shouldn't be responsible for redirecting in this case.
Try to move the Redirect thing to router as a best practice

Resources