twoam
twoam

Reputation: 892

Pass state to a component in another file in react

I have an App component with a few components in it for example menu, sidebar, repos etc. In the menu component there is a search bar. When you submit whatever you typed in the search bar it does a request to https://api.github.com/users/. Then I change the json to user state. But how do I pass the data to repos component? Is this possible?

App.js

import React, { Component } from 'react';
import Sidebar from './layout/Sidebar';
import Menu from './layout/Menu';
import Repos from './githubdata/Repos';
import Followers from "./githubdata/Followers";
import Following from "./githubdata/Following";
import BirthCount from "./githubdata/BirthCount";

class App extends Component{
    render(){
        return(
            <div className="wrapper">
                <Sidebar />
                <div className="main-panel">
                    {* In this component the magic happens *}
                    <Menu />
                    <div className="content">
                        <div className="container-fluid">
                            <div className="row">
                                {* I want to display the data in this component *}
                                <Repos />
                                <Followers />
                                <Following />
                                <BirthCount />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

export default App;

Menu.js

import React, { Component } from 'react';

class Menu extends Component {
    constructor(props){
        super(props);
        this.state = {
            query: ''
        }
    }

    handleChange = (event) => {
        this.setState({
            query: event.target.value
        })
    };

    search = () => {
        const BASE_URL = 'https://api.github.com/users/';
        let FETCH_URL = `${BASE_URL}${this.state.query}`;
        console.log('fetchurl', FETCH_URL)

        fetch(FETCH_URL, {
            method: 'GET'
        })
            .then(response => response.json())
            .then(json => {
                const user = json;
                console.log('user json', user);
                this.setState({
                    user
                })
            });
    };

    render(){
        return(
            <div>
                <input onChange={this.handleChange} value=this.state.query} type="text"/>
                <button onClick={this.search}>submit</button>
            </div>
        )
    }
}
export default Menu;

Upvotes: 4

Views: 8496

Answers (5)

Anurag Awasthi
Anurag Awasthi

Reputation: 6223

Move your search function to parent component App.

In Repo you can get by users by this.props.user

App.js

import React, { Component } from "react";
import Sidebar from "./layout/Sidebar";
import Menu from "./layout/Menu";
import Repos from "./githubdata/Repos";
import Followers from "./githubdata/Followers";
import Following from "./githubdata/Following";
import BirthCount from "./githubdata/BirthCount";

class App extends Component {
  constructor() {
    super();
    this.state = { user };
  }
  search = (query) => {
    const BASE_URL = "https://api.github.com/users/";
    let FETCH_URL = `${BASE_URL}${query}`;
    console.log("fetchurl", FETCH_URL);

    fetch(FETCH_URL, {
      method: "GET"
    })
      .then(response => response.json())
      .then(json => {
        const user = json;
        console.log("user json", user);
        this.setState({
          user
        });
      });
  };

  render() {
    return (
      <div className="wrapper">
        <Sidebar />
        <div className="main-panel">
          {/* In this component the magic happens */}
          <Menu search={this.search.bind(this)} />
          <div className="content">
            <div className="container-fluid">
              <div className="row">
                {/* I want to display the data in this component */}
                <Repos user={this.state.user} />
                <Followers />
                <Following />
                <BirthCount />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default App;

Upvotes: 2

hannad rehman
hannad rehman

Reputation: 4331

here is what you need to do if you are not using redux/flux.

class App extends Component{
constructor(props){
   super(props);
     this.state={results:[]};
  this.dataFromSearch=this.dataFromSearch.bind(this);
}
dataFromSearch(data){
this.setState({results:data});
}
render(){
    return(
        <div className="wrapper">
            <Sidebar />
            <div className="main-panel">
                {* In this component the magic happens *}
                {* dataFromSearch will be called when you actually have data 
                   you can pass the same props into the next child of Menu 
                *}
                <Menu callbackFn={this.dataFromSearch} />
                <div className="content">
                    <div className="container-fluid">
                        <div className="row">
                            {* I want to display the data in this component *}
                            <Repos searchData={this.state.results} />
                            <Followers />
                            <Following />
                            <BirthCount />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}

}

Call the props method in MENU when you have the data

class Menu extends Component {
constructor(props){
    super(props);
    this.state = {
    }
}

search = () => {
    const BASE_URL = 'https://api.github.com/users/';
    let FETCH_URL = `${BASE_URL}${this.state.query}`;
    console.log('fetchurl', FETCH_URL)

    fetch(FETCH_URL, {
        method: 'GET'
    })
        .then(response => response.json())
        .then(json => {
            const user = json;
            console.log('user json', user);
            this.setState({
                user
            })  
            // this will call the fn in App and your app state will be 
            //updated
            this.props.callbackFn(user);
        });
}; 

render(){
    return(
        <div>
            {// providing `onChange` callback and `query` value from props}
            <input onChange={this.props.onChange} value={this.props.query} type="text"/>
            <button onClick={this.search}>submit</button>
        </div>
    )
}

}

so after all execution your App state will have the data , that is passed to Repo component as Props. you can access it there easily/

Upvotes: 1

Malkio
Malkio

Reputation: 31

Yes this is possible. You'll have to use something called props https://facebook.github.io/react-native/docs/props.html

// APP.JS
.....
<div className="row">
   {* I want to display the data in this component *}
        <Repos data={dataToBePassed} />
        <Followers />
        <Following />
        <BirthCount />
   </div>
.....


// REPOS.JS
...
render(){
     return (<div>{this.props.datatobepassed}</div>)
}
....

Upvotes: 1

1ven
1ven

Reputation: 7016

You could achieve this by moving a state in App component:

class App extends Component{
    constructor(props){
        super(props);
        this.state = {
            query: ''
        }
    }

    handleChange = (event) => {
        this.setState({
            query: event.target.value
        })
    }

    render(){
        return(
            <div className="wrapper">
                <Sidebar />
                <div className="main-panel">
                    {* Provide the query value to Menu component *}
                    <Menu onChange={this.handleChange} query={this.state.query} />
                    <div className="content">
                        <div className="container-fluid">
                            <div className="row">
                                {* And provide the same data to Repos component *}
                                <Repos query={this.state.query} />
                                <Followers />
                                <Following />
                                <BirthCount />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

Next, you can remove state handling from Menu component:

class Menu extends Component {
    constructor(props){
        super(props);
        this.state = {
        }
    }

    search = () => {
        const BASE_URL = 'https://api.github.com/users/';
        let FETCH_URL = `${BASE_URL}${this.state.query}`;
        console.log('fetchurl', FETCH_URL)

        fetch(FETCH_URL, {
            method: 'GET'
        })
            .then(response => response.json())
            .then(json => {
                const user = json;
                console.log('user json', user);
                this.setState({
                    user
                })
            });
    };

    render(){
        return(
            <div>
                {// providing `onChange` callback and `query` value from props}
                <input onChange={this.props.onChange} value={this.props.query} type="text"/>
                <button onClick={this.search}>submit</button>
            </div>
        )
    }
}

Upvotes: 0

AKX
AKX

Reputation: 168863

You will need to lift that state up from the Menu component, to the "owning" App component, then pass it down to Repos, Followers, etc.

Upvotes: 0

Related Questions