1

How can I use the value from the input form and only make an api call when the button is submitted? Right now when I press submit I am receiving back the user name which is what I expect and want to receive, however it doesn't seem to be sending the information back to userCard. I realize right now I'm not calling it in the form but I'm a bit unsure how to approach this one.

import React,{useEffect, useState} from "react";
import {Form, Button} from "react-bootstrap"
import axios from "axios";
import UserCard from "./Card";



const UserForm = () => {

    const[user, setUser] = useState("");
    const[login, setLogin] =  useState("");
  const handleChange = (e) =>{
        //console.log(e.target.value)
        setUser(e.target.value);
    }

    const handleSubmit = (e) =>{
        //e.preventDefault();
        console.log("Button was submitted",user);
        axios.get(`https://api.github.com/users/${user}`)
        .then((res => 
            {setLogin(res.data);
         
            })
        )
          .catch(err => console.log(err));
    }

    return (
        
        <div className = "Form">
        <Form  onSubmit={handleSubmit} onChange = {handleChange} spellcheck="false" >
       <Form.Group controlId="formName">
            <Form.Label> Github Handle </Form.Label>
            <Form.Control type="text" placeholder="Enter Handle Here" />
        </Form.Group>
        <Button onClick = {handleSubmit}>Submit</Button>
        
        </Form>

        </div>
    )
}

export default UserForm;
import React from "react"
import { NavLink } from "react-router-dom"
import UserForm from "./UserForm"

const UserCard = (props) =>{
        return(
         <div className = "Card">
            <UserForm /> 
            <h1>Hello, {props.login}</h1>
            <h2>How is the weather in {props.location}?</h2>
            <h3>Here's a little about you </h3>
            <p>{props.bio}</p>
            <nav>
            <ul className = "cardlist">
            <li><NavLink to = "/followers" style={{ textDecoration: 'none' }}>Go To Followers</NavLink></li>
            <li><NavLink to = "/repos" style={{ textDecoration: 'none' }}>Go To Repos</NavLink> </li>
            </ul>
            </nav>
            </div>
        )
    }

export default UserCard;

import './App.css';
import React from "react";
import axios from "axios";
import { BrowserRouter, Link, Route } from 'react-router-dom';
import UserCard from "./components/Card";
import Followers from "./components/Followers";
import Repos from "./components/Repos";
import UserForm from "./components/UserForm"

let followerArray = [];

class App extends React.Component {

  state = {
    user: '' ,
    location : '',
    bio: '',
    followers: [],
    repos: []

  }
   
  //make api calls after the component mounts --> equivalent to useEffect()
  //componentDidUpdate is equivalent to useEffect(,[])
  componentDidMount() {
    console.log("Component mounted");
    //get user data
   
        console.log("finished")

        //get repos
       
  }

  render()
  {
  return (
    <BrowserRouter>
    <div className="App">
            <Route exact path = "/">
          <UserCard  name = {this.state.name} 
          login = {this.state.user} 
          location = {this.state.location} 
          bio = {this.state.bio}
          />
    </Route>
    <Route path = "/followers"  followers ={this.state.followers}>
    <Followers />
    </Route>
    <Route path = "/repos">
    <Repos repos={this.state.repos}/>
    </Route>
    </div>
    
    </BrowserRouter>
    

  );
  }
}

export default App;
5
  • Are you wanting to pass the login "state" to the UserCard component, wherever it's being rendered? Can you share a more comprehensive code example showing how and where you render both these components? As far as I can tell, your API call is already dynamic since it uses the current user state value when making the GET request. Commented Aug 8, 2021 at 4:57
  • You probably also want to keep the e.preventDefault(); in the form's submit handler so the default form action isn't taken and reloads the page/app. Commented Aug 8, 2021 at 5:03
  • Yes exactly, I want the login user name to be passed to Usercard. I'm rendering it in App and I've edited code. I know this is wrong but when I'm not sure how to approach. Commented Aug 8, 2021 at 5:07
  • I will uncomment that piece. Thank you Commented Aug 8, 2021 at 5:07
  • 2
    Ok, Danial's answer below is what I'd suggest... lifting the state into the parent component and passing down state and callbacks as props. Commented Aug 8, 2021 at 5:13

2 Answers 2

3

When you want to get back some values from child component, you can pass a function to child component. In your case:

  1. Define a Callback function in UserCard component and use the callback function data in card:
import React from "react"
import { NavLink } from "react-router-dom"
import UserForm from "./UserForm"

const UserCard = (props) =>{
    const[user, setUser] = useState("");
    const[login, setLogin] =  useState("");
    const giveBackDataToCard = (login , user) => {
       setLogin(login);
       setUser(user);
    }

        return(
         <div className = "Card">
            <UserForm /> 
            <h1>Hello, {login}</h1>
            <h2>How is the weather in {user.location}?</h2>
            <h3>Here's a little about you </h3>
            <p>{user.bio}</p>
            <nav>
            <ul className = "cardlist">
            <li><NavLink to = "/followers" style={{ textDecoration: 'none' }}>Go To Followers</NavLink></li>
            <li><NavLink to = "/repos" style={{ textDecoration: 'none' }}>Go To Repos</NavLink> </li>
            </ul>
            </nav>
            </div>
        )
    }

export default UserCard;
  1. Call props function where you want:
import React,{useEffect, useState} from "react";
import {Form, Button} from "react-bootstrap"
import axios from "axios";
import UserCard from "./Card";

const UserForm = () => {

    
    const handleChange = (e) =>{
        setUser(e.target.value);
    }

    const handleSubmit = (e) =>{
        e.preventDefault();
        axios.get(`https://api.github.com/users/${user}`)
        .then((res => 
            {
                setLogin(res.data);
//------------> For example here
                props.giveBackDataToCard(res.data,e.target.value);

            })
        )
          .catch(err => console.log(err));
    }

    return (
        
        <div className = "Form">
        <Form  onSubmit={handleSubmit} onChange={handleChange} spellcheck="false" >
       <Form.Group controlId="formName">
            <Form.Label> Github Handle </Form.Label>
            <Form.Control type="text" placeholder="Enter Handle Here" />
        </Form.Group>
        <Button onClick = {handleSubmit}>Submit</Button>
        
        </Form>

        </div>
    )
}

export default UserForm;
Sign up to request clarification or add additional context in comments.

1 Comment

This definitely helped me. Thank you!
0

Well, If your question is if you want send back the data to the userCard from userForm, You should follow these methods. First method is, You should learn first a Context APIs in react which already mentioned in docs https://reactjs.org/docs/context.html , use it for passing data between a screen. Second method is, Always call the API at parent level component, I think its a better and easier way. By calling API from parent level component you will have to pass some props to according to your useForm required. Third method is, The best way to use some state management store, like Mobx, Redux etc... It is a best way. You can then actually pass your state dynamically to your useCard component.

If answer matched you question, that will great, If not tell so that I will delete for community help.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.