Understanding React browser history - reactjs

I am building a web app using react 16 and react-router v4. My app has index.js like this -
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import Bootstrap from "bootstrap/dist/css/bootstrap.css";
import 'font-awesome/css/font-awesome.min.css';
import "../assets/css/clean-blog.css";
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter> ,
document.getElementById('app')
);
My App.js looks like this -
"use strict";
import React from "react";
import Header from "./layout/header";
import Body from "./layout/body";
import Footer from "./layout/footer";
class App extends React.Component {
render() {
return (
<div>
<Header />
<Body />
<Footer />
</div>
);
}
};
export default App;
In my Header component, I have a search box and I want that when user clicks on seacrh submit button, then they should be redirected to /seacrh url. I managed to get that. Please look at handleSubmit function
"use strict";
import React from "react";
import { Link } from 'react-router-dom';
import Notifications, {notify} from 'react-notify-toast';
import { withRouter } from 'react-router-dom';
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
searchTerm:''
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({searchTerm: event.target.value});
}
handleSubmit(event) {
event.preventDefault();
//console.log(this.props);
//console.log(this.state.searchTerm);
this.props.history.replace({
pathname:'/search',
searchTerm:this.state.searchTerm
});
}
render() {
return (
<nav className="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div className="container">
<Link to='/'>My Library</Link>
<button className="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
Menu
<i className="fa fa-bars"></i>
</button>
<div className="collapse navbar-collapse" id="navbarResponsive">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<Link to='/'>Home</Link>
</li>
<li className="nav-item">
<Link to='/authors'>Authors</Link>
</li>
<li className="nav-item">
<Link to='/books'>Books</Link>
</li>
</ul>
<form className="form-inline my-2 my-lg-0" onSubmit={this.handleSubmit} type="post">
<input className="form-control mr-sm-2" type="text" placeholder="Search" onChange={this.handleChange} name="searchTerm"/>
<button className="btn btn-outline-secondary btn-md " type="submit">Search</button>
</form>
</div>
</div>
</nav>
);
}
};
export default withRouter(Header);
This works fine when for all urls except when I try to submit from /search url then nothing happens. What I mean is that handleSubmit function gets called but then it does not fire the redirect call.
I am very new to react and would like to have some insight on how best should I handle this.

Related

passing component & props in function react js

i have 2 components & i want to pass data by input from parent component to the child component, i got stuck to pass the data to the child component and display or render the child component
is there any technique to pass the props to the child components & render it?
and when i see the console on developer tools there is nothing wrong/happen except the console.log code
import React, {Component} from 'react';
import ReactDOM from'react-dom';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
//props.keyword
const keyword = 'avenger';
const API = `https://api.themoviedb.org/3/search/movie?api_key=341c549444f65b6a022eea5fc24f5b77&language=en-US&query=${keyword}&page=1&include_adult=false`;
const DEFAULT_QUERY = 'redux';
class MovieSearch extends Component{
constructor(props){
super(props);
this.state={
movies:[]
}
}
componentDidMount(){
fetch(API + DEFAULT_QUERY)
.then(response=>response.json())
.then(data=>{
this.setState({movies:data.results})
})
}
render(){
const {movies} = this.state;
return(
<div className="row container">
{movies.map(movie =>
<div className="col-md-4">
<div className="card" style={{width: '15rem'}} key={movie.id}>
<img src="" className="card-img-top" alt="..."/>
<div className="card-body">
<h5 className="card-title">{movie.title}</h5>
<p>{movie.id}</p>
<Link to="/movie/detail">Detail</Link>
</div>
</div>
</div>
)}
</div>
)
}
}
export default MovieSearch;
import React, { Component } from"react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
//component
import Jumbotron from "./jumbotron";
import MovieList from "./movieList";
import MovieSearch from"./MovieSearch";
import Movie from"./Movie";
//HOC
const idMovie = (WrappedComponent)=>{
class IdMovie extends Component{
constructor(props){
super(props)
this.state={}
}
}
}
//route start here
class Main extends Component{
constructor(props){
super(props)
this.state={
keyword: ''
}
this.handleInput = this.handleInput.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleInput(event){
this.setState({keyword:event.target.value})
}
handleSubmit(event){
console.log(this.state.keyword)
event.preventDefault()
}
render(){
return (
<Router>
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<Link className="navbar-brand" to="/">Carifilm</Link>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav mr-auto">
<li className="nav-item active">
<Link className="nav-link" to="/">Home <span className="sr-only">(current)</span></Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/movies">Movies</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/search-movie">Cari film</Link>
</li>
</ul>
<form className="form-inline my-2 my-lg-0" onSubmit={this.handleSubmit}>
<input className="form-control mr-sm-2"
type="search" placeholder="Search"
aria-label="Search"
value={this.state.keyword}
onChange={this.handleInput}/>
<button className="btn btn-outline-success my-2 my-sm-0" type="submit" value="submit">Search</button>
</form>
</div>
</nav>
<Switch>
<Route exact path="/">
<Home/>
</Route>
<Route path="/movies">
<Movies/>
</Route>
<Route path="/movie/detail">
<MovieDetail/>
</Route>
<Route path="/search-movie">
<CariFilm/>
</Route>
</Switch>
</Router>
)}
}
export default Main;
function Home(){
return(
<Jumbotron/>
)
}
function Movies(){
return(
<MovieList/>
)
}
function MovieDetail(){
return(
<Movie/>
)
}
function CariFilm(props){
return(
<MovieSearch/>
)
}
Please check this example. Here I passed items into my Child Component and displayed items in child component.
Parent
import React, {Component, useEffect, useState} from 'react';
import {PChild} from "./PChild";
export class Parent extends Component {
constructor(props) {
super(props);
this.state = {items: []};
}
componentDidMount() {
let json = [];
json.push({track: { id:1, name: 'Black Sabbath, from the album Black Sabbath (1970)'}});
json.push({track: { id:2, name: 'Blackfield, from the album Blackfield (2004)'}});
json.push({track: { id:3, name: 'Bo Diddley, from the album Bo Diddley (1958)'}});
json.push({track: { id:4, name: 'Damn Yankees, from the album Damn Yankees (1990)'}});
this.setState({items: json});
}
render() {
return (
<div>
<PChild items={this.state.items} name="Khabir"/>
</div>
);
}
}
Child
import React, {useEffect, useState} from 'react';
// Parent to Child communication
export class PChild extends React.Component {
componentDidUpdate() {
console.log(this.props.items);
console.log(this.props.name);
}
render() {
return (
<div>
{this.props.items.map((item, i) => {
return <li key={item.track.id}>
{(`Item ${i+1} - ${item.track.name}`)}
</li>
})}
</div>
);
}
}

In react why error is showing like this --> 'customerSignup' is not defined

I am working on react project and I am trying to post data to database by using axios library in react. But I am getting this kind of error --> 'customerSignup' is not defined. I am trying to solve this error, but I am not, so please help to solve this error and help me to send data from front-end to backend.
This is App.js
import React from 'react';
import './App.css';
import Navbar from './Components/Navbar/Navbar';
import Home from './Pages/Home/Home';
import Signup from './Pages/Signup/Signup';
import { BrowserRouter as Router,Switch,Route,} from "react-router-dom";
function App() {
return (
<div className="App">
<Router>
<Navbar></Navbar>
<Switch>
<Route exact path='/'><Home></Home></Route>
<Route path= '/signup'><Signup></Signup></Route>
</Switch>
</Router>
</div>
);
}
export default App;
This is Navbar.js
import React from 'react';
import './Navbar.css';
import { Link } from 'react-router-dom';
export default function Navbar() {
return (
<div className='container'>
<div className='row'>
<div className='col-12'>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<a className="navbar-brand" href="#">Navbar</a>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav">
<li className="nav-item active">
<Link className='nav-link' to='/'>Home</Link>
</li>
<li className="nav-item">
<Link className='nav-link' to='/signup'>Signup</Link>
</li>
</ul>
</div>
</nav>
</div>
</div>
</div>
)
}
This is Signup.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './Signup.css';
export default function Signup() {
const Signup = () => {
const [customerSignUp, setCustomerSignUp] = useState([
{ email: '', password: '', firstName: '', lastName: ''}
]);
const handleChange = (event) => {
setCustomerSignUp({...customerSignup, [event.target.name]: event.target.value})
}
const handleSubmit = (e) => {
e.preventDefault()
axios.post('http://localhost:9000/api/signup', customerSignup)
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
})
}
return (
<div className="container">
<form className='white' onSubmit={handleSubmit}>
<h5 className="grey-text.text-darken-3">Sign Up With Email</h5>
<div className="input-field">
<label htmlFor="lastName">Last Name</label>
<input type="text" name="lastName" value={customerSignUp.lastName} onChange={handleChange} required />
</div>
<div className="input-field">
<button className="btn blue darken-3" type="submit">Sign Up</button>
</div>
</form>
</div>
);
}
}
`````
Your capitalization is wrong.
Change this:
const [customerSignUp, setCustomerSignUp] = ...
to this:
const [customerSignup, setCustomerSignUp] = ...
Notice the spelling difference between Signup and SignUp. Also make the changes elsewhere in the code where needed.

Redirect to another component after submit in react

I am new to React. I would like to redirect to another page (another component) called MainModule from the login form after clicking the submit button.
This is my Login Form=>
import React, {Component} from "react";
import { withRouter} from 'react-router-dom';
import {Button,FormGroup,FormControl,FormLabel,Form} from "react-bootstrap";
class Login extends Component {
constructor(props){
super(props);
this.state={
email:"",
password:""
};
}
handelChange = event =>{
this.setState({
[event.target.id]:event.target.value
},()=>{
});
}
handelSubmit = event => {
event.preventDefault();
this.props.history.push('/MainModule');
}
render()
{
return (
<div className="Login">
<Form onSubmit={this.handelSubmit}>
<FormGroup controlId="email">
<FormLabel>Email</FormLabel>
<FormControl autoFocus type="email" value={this.state.email} onChange={this.handelChange}/>
</FormGroup>
<FormGroup controlId="password">
<FormLabel>Password</FormLabel>
<FormControl type="password" value={this.state.password} onChange={this.handelChange}/>
</FormGroup>
<Button type="submit">Login</Button>
</Form>
</div>
)
}
}
export default withRouter(Login);
but the problem is after I clicking the submit button, url change to MainModule but MainMoudle form is not shown and just showing the current login form.I think this needs to defind the route for MainModule and I don't know how to do that. Please help.
Update
My MainModules =>
import React from 'react';
import { Route, Link,Switch,BrowserRouter } from "react-router-dom";
import allowance from './components/master/allowance';
class MainModule extends React.Component {
// constructor(props){
// super(props)
// }
render(){
return(
<div className="mainform">
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<Link className="navbar-brand" to="/MainModule">TMS</Link>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNavAltMarkup">
<div className="navbar-nav">
<Link className="nav-item nav-link" to={'/allowance'}>Allowance</Link>
</div>
</div>
</nav>
<div id="maincontent">
<Route path='/allowance' component={allowance} />
</div>
</div>
)
}
}
export default MainModule;
You are correct, you do have to define a route for your MainModule component.
In your App.js file, which is where I'm assuming you have set up your Routes:
import React from "react"
import { BrowserRouter, Route } from "react-router-dom"
import Login from "/yourcomponentfolder/Login"
import MainModule from "/yourcomponentfolder/MainModule"
const App = () => {
return(
<BrowserRouter>
<div>
//Using exact tells react-router that you will only render this component if the URL matches exactly with the path definition.
<Route path="/" component={Login} exact/>
<Route path="/MainModule" component={MainModule}/>
</div>
</BrowserRouter>
)
}
It's pretty cut and dry, you use the Route component, give it a path, and a component to render.

Calling function in App.js from another component

I'm new to ReactJS and want to use this library: https://github.com/teodosii/react-notifications-component
It states that "You must place ReactNotificationsComponent component at the root level of the application in order to work properly, otherwise it might conflict with other DOM elements due to the positioning."
I followed the usage guide, but I'm not sure how to call the addNotification function from a child component.
App.js
import React, { Component } from 'react'
import ReactNotification from "react-notifications-component"
import Header from './components/Header'
class App extends Component {
constructor() {
super()
this.addNotification = this.addNotification.bind(this)
this.notificationDOMRef = React.createRef()
}
addNotification() {
this.notificationDOMRef.current.addNotification({
title: "Awesomeness",
message: "Awesome Notifications!",
type: "success",
insert: "top",
container: "top-right",
animationIn: ["animated", "fadeIn"],
animationOut: ["animated", "fadeOut"],
dismiss: { duration: 5000 },
dismissable: { click: true }
})
}
render() {
return (
<div>
<ReactNotification ref={this.notificationDOMRef} />
<Header />
</div>
)
}
}
export default App
Header.js
import React, { Component } from 'react'
import logo from "../assets/images/logo/logo-light.png"
import { BrowserRouter as Router, Route, NavLink, Switch } from "react-router-dom"
import Home from '../pages/Home'
import Apply from '../pages/Apply'
export default class Header extends Component {
render() {
return (
<Router>
<div>
<Route render={({ location }) => (
<header id="navbar-spy" className="header header-1 header-dark header-fixed">
<nav id="primary-menu" className="navbar navbar-fixed-top">
<div className="container">
<div className="navbar-header">
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse-1" aria-expanded="false">
<span className="sr-only">Toggle navigation</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<img className="logo-light" src={logo} alt="Logo" draggable="false" />
</div>
<div className="collapse navbar-collapse pull-right" id="navbar-collapse-1">
<ul className="nav navbar-nav nav-pos-right navbar-left">
<li className="">
<NavLink to="/" className="menu-item">Home</NavLink>
</li>
<li className="">
<NavLink to="/apply" className="menu-item">Apply</NavLink>
</li>
</ul>
</div>
</div>
</nav>
</header>
)}
/>
<Route path="/" exact component={Home} />
<Route path="/apply" exact component={Apply} />
</div>
</Router>
)
}
}
When you click the "Apply" link, it loads the Apply component. In that component, they can receive an error/success notification. From that component is where I want to be able to tell the ReactNotification in App.js what title, message, and type to render. How can I communicate from Apply.js to App.js?
You can pass the addNotification function to your Header component:
<Header addNotification={this.addNotification} />
And you can continue to pass it down to other child components, until you are ready to call it.

how to add a search component in react?

I am transforming my current app into React, current ap is using jquery and PHP.
current search bar
<ul class="token-input">
<li class="token-">
<input name="p" type="password" autocomplete="new-password" value="" data-open="false" class="form-control" placeholder="password protected.">
</li>
</ul>
react header
import React from 'react';
import { FormattedMessage } from 'react-intl';
import styled from 'styled-components';
import A from './A';
import Img from './Img';
import NavBar from './NavBar';
import HeaderLink from './HeaderLink';
import messages from './messages';
import SearchBar from '../SearchBar';
import UserNavbar from '../UserNavbar';
import logoImage from './logo.png';
import backgroundImage from './bg.png';
import './Header.css';
const HeaderImage = styled.div`
background-image: url(${backgroundImage});
`;
/* eslint-disable react/prefer-stateless-function */
class Header extends React.Component {
render() {
return (
<header>
<HeaderImage className="navbar navbar-primary bg-dark shadow-sm">
<div className="container d-flex justify-content-between">
<A
to="/"
className="navbar-brand d-flex align-items-center"
>
<Img src={logoImage} />
<span className="slogan d-none d-md-block"> </span>
</A>
<SearchBar className="search-bar" />
<UserNavbar />
</div>
</HeaderImage>
<div className="tab-area">
<A href="" />
<NavBar>
<HeaderLink to="/">
<FormattedMessage {...messages.recent} />
</HeaderLink>
</NavBar>
</div>
</header>
);
}
}
export default Header;
can anyone please tell me how can I integrate this search field as 1 component inside the header? (and search is getting data from filter contents which are in the body of the website)
In SearchBar.js:
class SearchBar extends React.Component {
state = {
value: '',
}
handleChange = (e) => {
this.setState({
value: e.target.value,
});
}
handleSubmit = () => {
const { value } = this.state;
// do ajax request or something in order
// to submit and redirect to a different page
// containing search results
}
render() {
return (
<ul class="token-input">
<li class="token-">
<input
name="p"
type="password"
autocomplete="new-password"
value={this.state.value}
data-open="false"
className="form-control"
placeholder="password protected."
/>
</li>
</ul>
);
}
}
Then you would simply need to import the same way you did.

Resources