how to send value one component to another component in react js? - javascript

could you please tell me how to send input field value on second component on button click .I have one button and input field in first component.On button click I need to send input field value to second component
here is my code
http://codepen.io/naveennsit/pen/GZbpeV?editors=0010
var { Router, Route,browserHistory } = ReactRouter
class First extends React.Component{
sendValue(){
browserHistory.push('/second');
}
render(){
return (<div>
<input type='text' />
<button onClick={this.sendValue}>send</button>
</div>)
}
}
class Second extends React.Component{
render(){
return <div>second component</div>
}
}
class Main extends React.Component{
render(){
return (
<Router history={browserHistory}>
<Route path='/' component={First}></Route>
<Route path='/second' component={Second}></Route>
</Router>)
}
}
React.render( <Main />,document.getElementById('app'));
browserHistory.push('/')

The best solution would be to create some architecture that would allow you to have a separate state object, change it, and pass changes on to your components. See Flux, or Redux.
For a pinpointed solution, you could use url params:
class First extends React.Component{
sendValue(){
browserHistory.push('/second/' + this.refs.textField.value);
}
render(){
return (
<div>
<input type='text' ref='textField' />
<button onClick={() => {this.sendValue()}}>send</button>
</div>)
}
}
class Second extends React.Component {
render(){
return <div>second component: {this.props.params.test}</div>
}
}
class Main extends React.Component{
render(){
return (
<Router history={browserHistory}>
<Route path='/' component={First}></Route>
<Route path='/second/:test' component={Second}></Route>
</Router>)
}
}

thanks #omerts, by using refs is a best idea and also another way using state and i am also new to react.
var { Router, Route, browserHistory } = ReactRouter
class First extends React.Component{
constructor(props){
super(props);
this.sendValue = this.sendValue.bind(this);
this.setValue = this.setValue.bind(this);
this.state = {
userID: "#nageshwar_uidev"
};
}
setValue(e){
this.setState({
userID: e.target.value
});
}
sendValue(){
//console.log(this.state.userID);
browserHistory.push('/second/'+this.state.userID);
}
render(){
return (
<div>
<input type='text' value={this.state.userID} onChange={this.setValue} />
<button onClick={this.sendValue}>send</button>
</div>
)
}
}
class Second extends React.Component{
render(){
let { userID } = this.props.params;
return <div>The userID from first component is {userID} <a href="#" onClick={()=>browserHistory.push('/')}>back</a></div>
}
}
class Main extends React.Component{
render(){
return (
<Router history={browserHistory}>
<Route path='/' component={First}></Route>
<Route path='/second/:userID' component={Second}></Route>
</Router>)
}
}
React.render( <Main />,document.getElementById('app'));
browserHistory.push('/')
working example at codepen

Related

How to pass the state of the page to other React?

I want to know how I can pass a status from one page to another page for if used in the other way.
My first page Body.js (Which I handle the state):
import React from 'react';
import './Body.css';
import axios from 'axios';
import { Link } from "react-router-dom";
import User from './User';
class Body extends React.Component {
constructor (){
super();
this.state ={
employee:[],
employeeCurrent:[],
}
}
componentDidMount(){
axios.get('http://127.0.0.1:3004/employee').then(
response=>this.setState({employee: response.data})
)
}
getName = () => {
const {employee} = this.state;
return employee.map(name=> <Link className='link' to={`/user/${name.name}`}> <div onClick={()=>this.add(name)} key={name.id} className='item'> <img className='img' src={`https://picsum.photos/${name.name}`}></img> <h1 className='name'> {name.name} </h1></div> </Link>)
}
add = (name) => {
const nam = name;
this.state.employeeCurrent.push(nam)
console.log(this.state.employeeCurrent)
}
render(){
return(
<div className='body'>
{this.getName()}
</div>
)
}
}
export default Body;
My second page which I want to get the state called employeeCurrent:
import React from 'react';
import Header from './Header';
import Body from './Body';
class User extends React.Component {
constructor (props){
super(props);
this.props ={
employeeCurrent:[],
}
}
render(){
return(
<div >
{this.props.employeeCurrent}
</div>
)
}
}
export default User;
I'm using the React Router, it looks like this:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import './App.css';
import Home from './Home';
import User from './User';
const AppRouter = () => (
<Router>
<div className='router'>
<Route exact path="/" component={Home}/>
<Route path="/user/:id" component={User}/>
</div>
</Router>
);
export default AppRouter;
My project is:
Home page, where you have users, obtained from the API, all users have attributes (name, age, city and country). Saved in employeeCurrent variable:
What I want is: grab these attributes from the clicked user and play on the user page:
Someone would can help me PLEASE?????
Like I explained earlier, you need to lift the state up:
AppRouter (holds the state and passes it to children)
class AppRouter extends React.Component {
state = {
employeeCurrent: [],
employee: []
};
componentDidMount() {
axios
.get("http://127.0.0.1:3004/employee")
.then(response => this.setState({ employee: response.data }));
}
add = name => {
this.setState(prevState => {
const copy = prevState.employeeCurrent.slice();
copy.push(name);
return {
employeeCurrent: copy
};
});
};
render() {
return (
<Router>
<div className="router">
<Route
exact
path="/"
render={props => (
<Home
{...props}
add={this.add}
employee={this.state.employee}
currentEmployee={this.state.currentEmployee}
/>
)}
/>
<Route
path="/user/:id"
component={props => (
<User
{...props}
employee={this.state.employee}
currentEmployee={this.state.currentEmployee}
/>
)}
/>
</div>
</Router>
);
}
}
Body and User (receive parent state as props together with updater functions):
class Body extends React.Component {
getName = () => {
const { employee, add } = this.props;
return employee.map(name => (
<Link className="link" to={`/user/${name.name}`}>
{" "}
<div onClick={() => add(name)} key={name.id} className="item">
{" "}
<img
className="img"
src={`https://picsum.photos/${name.name}`}
/>{" "}
<h1 className="name"> {name.name} </h1>
</div>{" "}
</Link>
));
};
render() {
return <div className="body">{this.getName()}</div>;
}
}
class User extends React.Component {
render() {
// you will need to map employeeCurrent somehow
return <div>{this.props.employeeCurrent}</div>;
}
}

How to pass component reference to routes component in react

In react i want to pass a reference of component to routes component . But when i route to path such as '/' it re render the passed component so starts with 0 again.
Here is a Link of Working example
https://codesandbox.io/s/884yror0p2
Here is a code, whenever i route from Home-->About the about counter starts with 0.
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
class Dummy extends React.Component {
constructor(props) {
super(props);
this.state = {
c: 0
};
setInterval(() => {
this.setState({ c: this.state.c + 1 });
}, 1000);
}
render() {
return <h1> Counter {this.state.c}</h1>;
}
}
class BasicExample extends React.Component {
constructor(props) {
super(props);
this.state = {
// com: <Dummy /> this technique also not work
};
}
render() {
let com = <Dummy />;
return (
<div>
<Router>
<div>
{com}
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
<hr />
<Route
exact
path="/"
// render={() => <Home com={com} />} //this also not work
component={props => <Home {...props} com={com} />}
/>
<Route path="/about"
component={props => <About {...props} com={com} />}
/>
</div>
</Router>
</div>
);
}
}
class Home extends React.Component {
render() {
return (
<div>
{this.props.com}
<h2>Home </h2>
</div>
);
}
}
class About extends React.Component {
constructor(props) {
super(props);
console.log(this.props);
}
render() {
return (
<div>
{this.props.com}
<h2>About</h2>
</div>
);
}
}
ReactDOM.render(<BasicExample />, document.getElementById("root"));
You can’t pass a component by “reference”. However, if you would like to have the same data between all the components you could initialize your state in the parent component (BasicExample) and pass it down or use a state container like Redux.
You can the component down but the component will also go through a mounting process that will invalidate the state that you have stored in it.
If you need to hold the state, it should be stored in the parent component.
const Router = ReactRouterDOM.HashRouter;
const Route = ReactRouterDOM.Route;
const Link = ReactRouterDOM.Link;
class Dummy extends React.Component {
constructor(props) {
super(props);
this.state = {
c: props.c || 0
};
}
componentWillReceiveProps(nextProps) {
if (this.props.c !== nextProps.c) {
this.setState({
c: nextProps.c
});
}
}
render() {
return <h1> Counter {this.state.c}</h1>;
}
}
class BasicExample extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
setInterval(() => {
this.setState(prevState => {
return {
counter: prevState.counter + 1
};
});
}, 1000);
}
render() {
let Com = <Dummy c={this.state.counter} />;
return (
<div>
<h2>Main App</h2>
<Router>
<div>
{Com}
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
<hr />
<Route
exact
path="/"
// render={() => <Home com={com} />} //this also not work
render={props => (
<Home {...props} c={this.state.counter} Com={Dummy} />
)}
/>
<Route
path="/about"
render={props => (
<About {...props} c={this.state.counter} Com={Dummy} />
)}
/>
</div>
</Router>
</div>
);
}
}
class Home extends React.Component {
render() {
const Com = this.props.Com;
return (
<div>
<h2>Home </h2>
<Com c={this.props.c} />
</div>
);
}
}
class About extends React.Component {
constructor(props) {
super(props);
}
render() {
const Com = this.props.Com;
return (
<div>
<h2>About</h2>
<Com c={this.props.c} />
</div>
);
}
}
ReactDOM.render(<BasicExample />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/4.2.0/react-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.2.2/react-router-dom.js"></script>
<div id="root"></div>
Few things to note here are:
Use render property of Route to pass in any props
When you use component (instead of render or children, below) the
router uses React.createElement to create a new React element from the
given component. That means if you provide an inline function to the
component prop, you would create a new component every render. This
results in the existing component unmounting and the new component
mounting instead of just updating the existing component. When using
an inline function for inline rendering, use the render or the
children prop
Use function version of setState to refer to prevState

React js: can I pass data from a component to another component?

I'm new to React and I'm still learning it. I'm doing a personal project with it.
Let me explain my problem:
I have a component called <NewReleases /> where I make an ajax call and take some datas about some movies out on cinemas today. (I take title, poster img, overview etc...) I put all the data in <NewReleases /> state, so that state becomes an object containing an object for each movie and each object contains title poperty, poster property etc... Then I render the component so that it looks like a grid made by movies posters, infos and so on. And this works well.
Then I need a component <Movie /> to take some datas from the state of <NewReleases /> and render them on the HTML. I read other questions where people were having a similar problem, but it was different because they had a children component that was rendered by the parent component. And in that way, people suggested to pass state as props. I can't do that because my <Movie /> component is not rendered by <NewReleases />. <NewReleases /> makes the ajax call and only renders a JSX grid based on the retrieved data.
On index.js I have setup the main page this way:
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Switch, Route} from 'react-router-dom';
import {Home} from './home';
import {Movie} from './movie';
import './css/index.css';
class App extends React.Component {
render() {
return(
<BrowserRouter>
<Switch>
<Route path={'/movie/:movieTitle'} component={Movie} />
<Route path={'/'} component={Home} />
</Switch>
</BrowserRouter>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
(You can't see <NewReleases /> here because it is rendered inside of <Home /> component, which also renders a header and a footer.)
So when I click on a movie rendered by <NewReleases />, the app will let me go on localhost:3000/movie/:movieTitle where :movieTitle is a dynamic way to say the title of the movie (so for example if I click the poster of Star Wars rendered by <NewReleases />, I will go on localhost:3000/movie/StarWars). On that page I want to show detailed infos about that movie. The info are stored in <NewReleases /> state but I can't have access to that state from <Movie /> (I guess).
I hope you got what I want to achieve. I don't know if it is possible. I had an idea: on the <Movie /> I could do another ajax call just for the movie that I want but I think it would be slower and also I don't think it would be a good solution with React.
Note that I'm not using Redux, Flux etc... only React. I want to understand React well before to move to other technologies.
The way you wanna do is more complicated. With parents componentes that's easy to do. And with Redux is much more easy.
But, you wanna this way. I think if you have a state in the app, pass to home a props to set a movie-state and pass this movie-state to component Move, works fine.
The problem is that Route does't pass props. So there is a extensible route you can do. In the code below I get from web this PropsRoute.
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Switch, Route} from 'react-router-dom';
import {Home} from './home';
import {Movie} from './movie';
import './css/index.css';
class App extends React.Component {
constructor() {
super();
this.state = {
movie: {}
}
this.setMovie = this.setMovie.bind(this);
}
setMovie(newMovie) {
this.setState({
movie: newMovie
});
}
render() {
return(
<BrowserRouter>
<Switch>
<PropsRoute path={'/movie/:movieTitle'} movie={this.state.movie} component={Movie} />
<PropsRoute path={'/'} component={Home} setMovie={this.setMovie} />
</Switch>
</BrowserRouter>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
-----
const renderMergedProps = (component, ...rest) => {
const finalProps = Object.assign({}, ...rest);
return (
React.createElement(component, finalProps)
);
}
const PropsRoute = ({ component, ...rest }) => {
return (
<Route {...rest} render={routeProps => {
return renderMergedProps(component, routeProps, rest);
}}/>
);
}
I thinks this can solve your problem.
Here's a quick example. Store your state in a parent component and pass down the state down to your components. This example uses React Router 4, but it shows how you can pass down the setMovie function and movie information via state to one of your child components. https://codepen.io/w7sang/pen/owVrxW?editors=1111
Of course, you'll have to rework this to match your application, but a basic run down would be that your home component should be where you're grabbing your movie information (via AJAX or WS) and then the set function will allow you to store whatever information you need into the parent component which will ultimately allow any child components to access the information you have stored.
const {
BrowserRouter,
Link,
Route,
Switch
} = ReactRouterDOM;
const Router = BrowserRouter;
// App
class App extends React.Component{
constructor(props) {
super(props);
this.state = {
movie: {
title: null,
rating: null
}
};
this.setMovie = this.setMovie.bind(this);
}
setMovie(payload) {
this.setState({
movie: {
title: payload.title,
rating: payload.rating
}
});
}
render(){
return(
<Router>
<div className="container">
<Layout>
<Switch>
<Route path="/select-movie" component={ () => <Home set={this.setMovie} movie={this.state.movie} />} />
<Route path="/movie-info" component={()=><MovieInfo movie={this.state.movie}/>} />
</Switch>
</Layout>
</div>
</Router>
)
}
}
//Layout
const Layout = ({children}) => (
<div>
<header>
<h1>Movie App</h1>
</header>
<nav>
<Link to="/select-movie">Select Movie</Link>
<Link to="/movie-info">Movie Info</Link>
</nav>
<section>
{children}
</section>
</div>
)
//Home Component
const Home = ({set, movie}) => (
<div>
<Movie title="Star Wars VIII: The Last Jedi (2017)" rating={5} set={set} selected={movie} />
<Movie title="Star Wars VII: The Force Awakens (2015)" rating={5} set={set} selected={movie} />
</div>
)
//Movie Component for displaying movies
//User can select the movie
const Movie = ({title, rating, set, selected}) => {
const selectMovie = () => {
set({
title: title,
rating: rating
});
}
return (
<div className={selected.title === title ? 'active' : ''}>
<h1>{title}</h1>
<div>
{Array(rating).fill(1).map(() =>
<span>★</span>
)}
</div>
<button onClick={selectMovie}>Select</button>
</div>
)
}
//Movie Info
//You must select a movie before movie information is shown
const MovieInfo = ({movie}) => {
const {
title,
rating
} = movie;
//No Movie is selected
if ( movie.title === null ) {
return <div>Please Select a Movie</div>
}
//Movie has been selected
return (
<div>
<h1>Selected Movie</h1>
{title}
{Array(rating).fill(1).map(() =>
<span>★</span>
)}
</div>
)
}
ReactDOM.render(<App />,document.getElementById('app'));
nav {
margin: 20px 0;
}
a {
border: 1px solid black;
margin-right: 10px;
padding: 10px;
}
.active {
background: rgba(0,0,0,0.2);
}
<div id="app"></div>
Create a manual object store to get/set the movie information and use it. That's it. Try the following code. That should answer all your questions. Click on any of the new releases, it will redirect to movie info screen with all the details. If you feel bad about the new releases data always refreshing, you may have to create another store, then get/set the data by checking the data exist in store.
Note: Using store and using title(duplicates may occur) in browser URL makes some problems when user refreshes the browser. For that, use id in browser URL, fetch the details using AJAX call and set that details in store.
//store for movie info
const movieInfoStore = {
data: null,
set: function(data) {
this.data = data;
},
clear: function() {
this.data = null;
}
};
class MovieInfo extends React.Component {
componentWillUnmount() {
movieInfoStore.clear();
}
render() {
return (
<div>
<pre>
{movieInfoStore.data && JSON.stringify(movieInfoStore.data)}
</pre>
<button onClick={() => this.props.history.goBack()}>Go Back</button>
</div>
)
}
}
MovieInfo = ReactRouterDOM.withRouter(MovieInfo);
class NewReleases extends React.Component {
handleNewReleaseClick(newRelease) {
movieInfoStore.set(newRelease);
this.props.history.push(`/movie/${newRelease.title}`);
}
render() {
const { data, loading } = this.props;
if(loading) return <b>Loading...</b>;
if(!data || data.length === 0) return null;
return (
<ul>
{
data.map(newRelease => {
return (
<li onClick={() => this.handleNewReleaseClick(newRelease)}>{newRelease.title}</li>
)
})
}
</ul>
)
}
}
NewReleases = ReactRouterDOM.withRouter(NewReleases);
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
newReleases: [],
newReleasesLoading: true
};
}
componentDidMount() {
setTimeout(() => {
this.setState({
newReleases: [{id: 1, title: "Star Wars"}, {id: 2, title: "Avatar"}],
newReleasesLoading: false
});
}, 1000);
}
render() {
const { newReleases, newReleasesLoading } = this.state;
return (
<NewReleases data={newReleases} loading={newReleasesLoading} />
)
}
}
class App extends React.Component {
render() {
const { BrowserRouter, HashRouter, Switch, Route } = ReactRouterDOM;
return (
<HashRouter>
<Switch>
<Route path="/movie/:movieTitle" component={MovieInfo} />
<Route path="/" component={Home} />
</Switch>
</HashRouter>
)
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>
<div id="root"></div>

how to move second component in react js?

I am using react-router.js .I want to show / move to second component / page on click of button using react.js
can I move to second page / component on button click
here is my code
http://codepen.io/naveennsit/pen/RamvLj?editors=1010
var { Router, Route} = ReactRouter
class App extends React.Component {
render() {
return (<Router>
<Route path='/' component={first}></Route>
<Route path='/about' component={second}></Route>
</Router>)
}
}
class second extends React.Component {
render() {
return <label>second component</label>
}
}
class first extends React.Component {
handleClick(){
alert('--')
}
render() {
return <div>
<label>first component</label>
<button onClick={this.handleClick}>MOve to second page</button>
</div>
}
}
React.render( < App / > , document.getElementById('app'))
You can use Link from react-router
var { Router, Route, Link} = ReactRouter
class App extends React.Component {
render() {
return (<Router>
<Route path='/' component={first} />
<Route path='/about' component={second} />
</Router>)
}
}
class second extends React.Component {
render() {
return <label>second component</label>
}
}
class first extends React.Component {
render() {
return <div>
<label>first component</label>
<Link to='/about'><button>MOve to second page</button></Link>
{this.props.children}
</div>
}
}
React.render( < App / > , document.getElementById('app'))
Hope this helps

How implement a proper layout using reactjs and react-router

How can I implement a proper layout using reactjs and react-router.
Basically what I want to implement is something line the image below:
Note: I don't want implement the header & footer in the index.html.
So far what I have done and working is:
import React from 'react';
import { Router, Route, Link } from 'react-router'
class App extends React.Component {
render(){
return <div>
<h1>App</h1>
<ul>
<li><Link to="/home">Home</Link></li>
<li><Link to="/blog">Blog</Link></li>
<li><Link to="/portfolio">Portfolio</Link></li>
<li><Link to="/social">Social</Link></li>
<li><Link to="/about">about</Link></li>
</ul>
{this.props.children}
</div>
}
}
class Home extends React.Component {
render(){
return <p>home</p>
}
}
class Blog extends React.Component {
render(){
return <p>blog</p>
}
}
class Portfolio extends React.Component {
render(){
return <p>portfolio</p>
}
}
class Social extends React.Component {
render(){
return <p>social</p>
}
}
class About extends React.Component {
render(){
return <p>about</p>
}
}
let routes = <Router>
<Route path="/" component={App}>
<Route path="home" component={Home} />
<Route path="blog" component={Blog} />
<Route path="portfolio" component={Portfolio} />
<Route path="social" component={Social} />
<Route path="about" component={About} />
</Route>
</Router>
React.render(routes, document.body);
The above code it's working properly, but What I need is separate the the App in 3 components - > <Header />, content and <Footer />
something like:
class App extends React.Component {
render(){
return <Header />
{this.props.children}
<Footer />
}
}
class Footer extends React.Component {
render(){
return <div>Footer</div>
}
}
class Header extends React.Component {
render(){
return <div>
<h1>App</h1>
<ul>
<li><Link to="/home">Home</Link></li>
<li><Link to="/blog">Blog</Link></li>
<li><Link to="/portfolio">Portfolio</Link></li>
<li><Link to="/social">Social</Link></li>
<li><Link to="/about">about</Link></li>
</ul>
</div>
}
}
but when I implement it the routing doesn't work and I don't get any error, I think is something related with the {this.props.children}, so.. any idea how can I get it done?
Your render function transpiles to:
function render() {
return React.createElement(Header, null);
{
this.props.children;
}
React.createElement(Footer, null);
}
You're not seeing any errors because this is valid, but has unreachable code. It just returns a Header element.
You need to wrap its contents in another element, e.g.:
class App extends React.Component {
render() {
return <div>
<Header/>
{this.props.children}
<Footer/>
</div>
}
}
Edit: Imagine you wrote this code outside the context of React - what would you expect it to return?
function render() {
return 'Header';
'Content';
'Footer';
}
These are 3 separate statements, and since the first statement is a return, the last 2 are irrelevant, as they'll never be reached.
In order to return multiple objects from a function, you need to put them in a container of some sort, e.g. an Array:
function render() {
return [
'Header',
'Content',
'Footer'
]
}
However, you can't do this in a React component's render() method, as they must return either a React component, null, or false, hence you need to wrap contents with another element if you want to return multiple items.

Categories

Resources