how to add a search component in react? - reactjs

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.

Related

Not able to get the value after updating the state

I have an application which has 3 pages .home ,shop,about.I want to add authentication to only page ie shop. When the user want to go to the shop page he has to login then only the user will go the shop page. I am maintaining a global state which has intital value isLogin:False. I extracted this value through mapStatetoProps in my App.js where all my Routes are there.For /shop path i am using the value as ternary condition. Initially the value (isLogin) is false it will render the Login page upon clicking shop link. But after proper authentication i am unable to redirect to the shop page
//App.js
import React ,{Component} from 'react';
import './App.css';
import Navigation from './Step1/Navbar'
import Home from './Step1/Home'
import Shop from './Step1/Shop'
import About from './Step1/About'
import Login from './LoginAuthentication/Loginform'
import {BrowserRouter as Router,Route} from 'react-router-dom'
import {connect} from 'react-redux'
const mapStateToProps=(state)=>{
console.log(state)
return{
isLogin:state.isLogin
}
}
class App extends Component {
render(){
return (
<Router>
<div className="App">
<Navigation/>
<Route path="/" exact component={Home}/>
<Route path="/about" component={About}/>
<Route path="/shop"
render={({isLogin}) =>(
isLogin ? <Shop/> : <Login/>
) }
/>
</div>
</Router>
);
}
}
export default connect(mapStateToProps,null)(App);
//Navigation
import React from 'react'
import {NavLink} from 'react-router-dom'
const Navbar=()=> {
return (
<div>
<nav className="navbar navbar-expand-sm bg-dark">
<ul className="navbar-nav">
<li className="nav-item"><NavLink to="/" >Home</NavLink> </li>
<li className="nav-item"><NavLink to="/shop">Shop </NavLink> </li>
<li className="nav-item"><NavLink to ="/About">About </NavLink> </li>
<li className="nav-item"><NavLink to ="/page">Page </NavLink> </li>
</ul>
</nav>
</div>
)
}
export default Navbar
// LoginForm.js
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {withRouter} from 'react-router-dom'
//import {Redirect} from 'react-router-dom'
import {action1} from '../Actions/action1'
const mapDispatchToProps=(dispatch)=>{
return{
LoginCheck:()=>dispatch(action1())
}
}
class Loginform extends Component {
state={
username:'',
password:'',
uname:'dharmendra',
pwd:'230498'
}
nameHandler=(event)=>{
if(event.target.name==='UserName'){
this.setState({username:event.target.value})
}
if(event.target.name==='Password'){
this.setState({password:event.target.value})
}
}
submitHandler=(event,state)=>{
event.preventDefault()
const uname=this.state.uname
const pwd=this.state.pwd
if(this.state.username===uname && this.state.password===pwd){
this.props.LoginCheck()
//return <Redirect to="/shop"/>
//this.props.history.push("/shop")
this.props.history.push("/page");
console.log('hi i am in shop page successful')
}
else{
alert("Enter proper Credentials")
}
}
render() {
return (
<div className="login">
<form onSubmit={this.submitHandler}>
<div className="form-group">
<h1>
<input
type="text"
placeholder="UserName"
value={this.state.username}
onChange={this.nameHandler}
className="form-control"
name="UserName"
/>
</h1>
</div>
<br></br>
<div className="form-group">
<h1>
<input
type="password"
placeholder="Password"
value={this.state.password}
onChange={this.nameHandler}
className="form-control"
name="Password"
/>
</h1>
</div>
<br></br>
<div className="form-group">
<button type="submit" className="btn btn-success" >Login</button>
</div>
</form>
</div>
)
}
}
export default withRouter(connect(null,mapDispatchToProps)(Loginform))
//reducer1.js
import {LOGINCHECK} from '../Constants/actiontypes'
const initialState={
isLogin:false
}
const reducer1=(state=initialState,action)=>{
//console.log(action.type)
//console.log(state)
if(action.type===LOGINCHECK){
return Object.assign({},state,{isLogin:true})
}
return state
}
export default reducer1
//action.js
import {LOGINCHECK} from '../Constants/actiontypes'
export const action1 =()=>{
return{
type:LOGINCHECK
}
}
Unable to redirect to the shop page even after proper authentication also
Change the route like this :
<Route path="/shop"
render={() =>(
this.props.isLogin ? <Shop/> : <Login/>
) }
/>
The props that are passed to the render prop in the Route components are route props, not the App component props (they don't contain isLogin)
https://reacttraining.com/react-router/web/api/Route/route-props

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.

Why is my component not effectively receiving props?

I keep getting a message that the item I'm trying to access via props is undefined. Can you please tell me why it's not working?
Here is where the instance where the props are attempting to be passed... I'm specifically talking about the tellus and yourTrial props.
import React from 'react'
import Info from './components/Info'
import Upsell from '../../../general/components/order/components/Upsell'
import FormTwo from '../../../general/components/forms/FormTwo'
import Footer from '../../../cbd-desktop/components/layout/Footer'
export default class Order extends React.Component {
render() {
return (
<div>
<div>
<div style={styles.header}>
<img style={styles.leaf} src="./resources/desktop-img/leaves_top.png" />
<img style={styles.logo} src="./resources/desktop-img/logo_white.png" />
</div>
<div style={styles.wrapper}>
<div style={styles.leftWrapper}>
<Info />
<Upsell styles={upsellStyles} />
</div>
<FormTwo styles={formStyles} tellus="Tell us where to send" yourTrial="YOUR TRIAL BOTTLE"} />
</div>
</div>
<Footer style={styles.footer}/>
</div>
)
}
}
And here is where I am trying to display these values on the child... towards the top in two h2s
import React from 'react'
import { connect } from 'react-redux'
import { stepTwoSubmit, saveBillingData } from
'../../actions/formStepTwoActions'
import { addReceiptProduct } from '../../actions/receiptActions'
import FormTwoInputs from './components/FormTwoInputsComponent.jsx'
import Throbber from '../throbber/Throbber'
import FormWarning from './components/FormWarningComponent.jsx'
import Button from '../../../cbd-desktop/components/layout/Button'
const mapStateToProps = state => ({
state:state,
config:state.config,
downsellProduct:state.downsell.downsellProduct || {},
receiptProducts:state.receipt.receiptProducts || []
})
const mapDispatchToProps = {
stepTwoSubmit,
saveBillingData,
addReceiptProduct
}
#connect(mapStateToProps, mapDispatchToProps)
export default class FormTwo extends React.Component {
constructor(props) {
super(props)
componentWillReceiveProps(nextProps) {
let formTwoResponse = nextProps.state.stepTwo.formTwoResponse
this.checkOrderStatus(formTwoResponse)
}
componentDidMount() {
this.fillMainOrder()
this.calculateViewers()
this.calculateTimer()
}
render() {
let { state, props, inputs, onInputFocus, saveInputVal, styles } = this,
CustomTag = props.labels ? 'label' : 'span',
{ submitting, formWarning } = state,
{ invalidInputID, text, visible } = formWarning
return (
<div style={styles.formWrapper}>
<p style={styles.yellowBanner}>{this.state.viewers} people viewing this product right now</p>
<div style={styles.formInnerWrapper}>
<div style={styles.headerWrapper}>
<h2 style={styles.header}>{this.props.tellus}</h2>
<h2 style={styles.header}>{this.props.yourTrial}</h2>
</div>
<div style={styles.weAccept}>
<p style={styles.weAcceptText}>We Accept:</p>
<img style ={styles.cardImage} src="resources/desktop-img/cards.png" />
</div>
<form onSubmit={this.submit}>
<FormTwoInputs onInputFocus={onInputFocus} saveInputVal={saveInputVal} CustomTag={CustomTag} styles={styles} />
<FormWarning visible={visible} invalidInputID={invalidInputID} text={text} />
<Button style={styles.button} buttonText="RUSH MY TRIAL" />
</form>
</div>
<img src="resources/desktop-img/secure.png" />
<div style={styles.urgencyWrapper}>
<div style={styles.urgencyTextWrapper}>
<span style={styles.redText}>{this.state.viewers} people are viewing this offer right now -</span>
<span style={styles.blueText}>{this.state.counter}</span>
</div>
<p style={styles.blueText}>Claim Your Bottle Now</p>
</div>
<Throbber throbberText='Confirming your shipment...' showThrobber={submitting} />
</div>
)
}
}

Understanding React browser history

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.

Get value of input and give to parent in React

I have the following two components App and it's child Toolbar.
Toolbar contains a form and and input, and I would like to pass the value from the input up to the App component's state -- but only when the use has confirmed it (on submit or enter etc).
My current attempt is not working as I only get a proxy and an event object back (which does makes sense). How would I do this?
I am not using Redux or anything like it.
App.js
import React, {Component} from 'react'
import {render} from 'react-dom'
import {} from './styles/base.scss'
import ImageContainer from './components/Images'
import Toolbar from './components/Toolbar'
export default class App extends Component {
constructor(props) {
super(props);
// http://www.cloudypoint.com/Tutorials/discussion/javascript-how-to-update-parents-state-in-react/
this.setFolderPathHandler = this.setFolderPathHandler.bind(this);
}
setFolderPathHandler(e) {
e.preventDefault();
console.log(arguments);
// this.setState({
// xyz: input
// });
}
render() {
return (
<div>
<Toolbar setFolderPathHandler={this.setFolderPathHandler} />
<ImageContainer />
</div>
)
}
}
Toolbar/index.js
import React, { Component } from 'react';
import path from 'path';
class Toolbar extends Component {
render() {
return (
<nav className="toolbar">
<div className="column">
{/* START used to be it's own component */}
<form onSubmit={this.props.setFolderPathHandler}>
<div className="form-field">
<input type="text" className="folder-path" ref={(input) => this.input = input} />
<button><i className="fa fa-fw fa-2x fa-folder-open" aria-hidden="true"></i></button>
</div>
</form>
{/* END used to be it's own component */}
</div>
<div className="column">
<button><i className="fa fa-fw fa-2x fa-chevron-left" aria-hidden="true"></i></button>
<button><i className="fa fa-fw fa-2x fa-chevron-right" aria-hidden="true"></i></button>
</div>
</nav>
);
}
}
export default Toolbar;
I did have the input as a separate component but it was too confusing to me (I am new to React).
App.js
import React, {Component} from 'react'
import {render} from 'react-dom'
import {} from './styles/base.scss'
import ImageContainer from './components/Images'
import Toolbar from './components/Toolbar'
export default class App extends Component {
constructor(props) {
super(props);
// http://www.cloudypoint.com/Tutorials/discussion/javascript-how-to-update-parents-state-in-react/
this.setFolderPathHandler = this.setFolderPathHandler.bind(this);
}
setFolderPathHandler(inputValue) {
// this.setState({
// xyz: inputValue
// });
}
render() {
return (
<div>
<Toolbar setFolderPathHandler={this.setFolderPathHandler} />
<ImageContainer />
</div>
)
}
}
Toolbar/index.js
import React, { Component } from 'react';
import path from 'path';
class Toolbar extends Component {
constructor(props) {
super(props);
this.submit = this.submit.bind(this);
}
submit(event) {
event.preventDefault();
this.props.setFolderPathHandler(this.input.value);
}
render() {
return (
<nav className="toolbar">
<div className="column">
{/* START used to be it's own component */}
<form onSubmit={this.submit.bind(this)}>
<div className="form-field">
<input type="text" className="folder-path" ref={(input) => this.input = input} />
<button><i className="fa fa-fw fa-2x fa-folder-open" aria-hidden="true"></i></button>
</div>
</form>
{/* END used to be it's own component */}
</div>
<div className="column">
<button><i className="fa fa-fw fa-2x fa-chevron-left" aria-hidden="true"></i></button>
<button><i className="fa fa-fw fa-2x fa-chevron-right" aria-hidden="true"></i></button>
</div>
</nav>
);
}
}
export default Toolbar;
First, if you want to track input value in toolbar, you should save it into state:
class Toolbar extends Component {
constructor(...args) {
super(...args)
this.state = {text: ''};
}
onTextChange(event) {
const text = event.target.value;
this.setState({text});
}
onSubmit(event) {
event.preventDefault();
this.props.setFolderPathHandler(this.state.text);
}
render() {
return (
<nav className="toolbar">
<div className="column">
<form onSubmit={this.onSubmit.bind(this)}>
<div className="form-field">
<input type="text" className="folder-path" value={this.state.text} onChange={this.onTextChange.bind(this)} />
<button><i className="fa fa-fw fa-2x fa-folder-open" aria-hidden="true"></i></button>
</div>
</form>
</div>
...
</nav>
);
}
}
export default Toolbar;
Note that we are keeping internally the value of the input and we are not passing the native events up to the parent controller.
Then in the parent controller:
setFolderPathHandler(input) {
// do something with the input
}
This solution has the problem that you cannot reset the input value from the parent component unless the component is removed from DOM and added again.
This is usually solved by putting the state to the parent component. The parent can then pass text and onChange handlers to the child that contains the <input> or, the parent can create the <input> and pass it to the child component as a property. Consider:
class Toolbar extends Component {
render() {
return (
<nav className="toolbar">
<div className="column">
<form onSubmit={this.props.onSubmit}>
<div className="form-field">
{this.props.textInput}
<button><i className="fa fa-fw fa-2x fa-folder-open" aria-hidden="true"></i></button>
</div>
</form>
</div>
...
</nav>
);
}
}
and App:
export default class App extends Component {
...
render() {
const textInput = (
<input ... value={this.state.text} onChange={this.onTextChange} />
);
return (
<div>
<Toolbar onSubmit={this.onSubmit} textInput={textInput} />
<ImageContainer />
</div>
)
}
}
This allows to separate components that handle the business logic (have state, smart components) and the components that only present things (stateless, dumb components).

Resources