'How to lift state from a form to another component?

I have been really struggling to lift the state of this form data to be sent with some other data that i'm already successfully posting to the backend. I'm trying to have the user enter their username in the top of the page and then send that username to the backend with the other data. When trying to console log the state when inside the component i want to lift it too, i was getting 'undefined' in the console for the longest time but now I'm getting a part of the form component that i created being displayed in the console when trying to console log the state. this is what is being displayed in the console when trying to log the state:

 "onLoad
 Flashcard.js:35 class NameForm extends react__WEBPACK_IMPORTED_MODULE_0__.Component {
 constructor(props) {
 super(props);

 this.handleChange = event => {
  this.setState({
    value: event.target.value
…

here is the code for my NameForm.js file which is where i create the form:

import React from "react"
import CheckGuess from './Flashcard'


export default class NameForm extends React.Component {
constructor(props) {
  super(props);
  this.state = {value: ''};   
  this.handleChange = this.handleChange.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);
}

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

handleSubmit = (event) => {  
    alert('A name was submitted: ' + this.state.value);
    this.props.CheckGuess(this.props.answer, this.state.value);
    event.preventDefault();
}
CheckGuess() {

}

render() {
  return (
      <div>
        <form onSubmit={this.handleSubmit}>
            <label>
                Name:
                <input type="text" value={this.state.value} onChange={this.handleChange} />
            </label>
            <input type="submit" value="Submit" />
            
        </form>
      </div>
  );
}
}

and here is the code for my flashcard.js file which contains the CheckGuess function which sends 
the 
other data to the backend and is where i would like to send the username as well:

export default function Flashcard({ flashcard }) {     // recieving flashcard prop from our 
mapping in flashcardlist.js, each w a unique id

const MAX_TRIES = 4
// const [incorrect, setIncorrect] = useState(incorrect)
const [guess, setGuess] = useState(0)
const [flip, setFlip] = useState(false)
const [height, setHeight] = useState('initial') //sets the state for our initial height to be 
replaced by the max height

const frontEl = useRef() // lets us have a reference from the front and back through every 
rerendering of them
const backEl = useRef()

// const callDouble = () =>{
 //   checkGuess();
  //  postData();
// } 


async function postData() {

    
}



const CheckGuess = (answer, stateValue) => {
    try {
        console.log(value)
        let result = fetch('http://127.0.0.1:5000/post', {
            method: 'POST',
            mode: 'no-cors',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',

            },
            body: JSON.stringify({
                key: `${Date.now()}`,
                question: flashcard.question,
                answer: flashcard.answer,
                options: flashcard.options,
                guess: answer,
                user: stateValue
            })
        });
    } catch(e) {
        console.log(e)
    }
    if (answer === flashcard.answer) {
        setFlip(true)
        return
    }
    if (guess + 1 === MAX_TRIES) {
        setFlip(true)
    }

    setGuess(guess + 1)
    // setIncorrect(true)
}

function setMaxHeight() {
    const frontHeight = frontEl.current.getBoundingClientRect().height //gives us dimensions of 
the rectangle but we only need the height
    const backHeight = backEl.current.getBoundingClientRect().height
    setHeight(Math.max(frontHeight, backHeight, 100)) // sets the height (setHeight) to the 
maximum height of front or back but the minimum is 100px
}

useEffect(setMaxHeight, [flashcard.question, flashcard.answer, flashcard.options]) //anytime any 
of these change then the setMaxHeight will change
useEffect(() => {
    window.addEventListener('resize', setMaxHeight) //everytime we resize our browser, it sets 
the max height again
    return () => window.removeEventListener('resize', setMaxHeight) //removes the eventlistener 
when component destroys itself
  }, [])


return (
<div 
    onClick={() => postData()}
    className={`card ${flip ? 'flip' : ''}`} // if flip is true classname will be card and flip, 
if flip isnt true it will just be card
    style={{ height: height }} //setting height to the variable height
    
    // onClick={() => setFlip(!flip)} // click changes it from flip to non flip
>
    <div className="front" ref={frontEl}>
        {flashcard.question}
        <div className='flashcard-options'>
            {flashcard.options.map(option => {
                return <div key={option} onClick={() => CheckGuess(option)} className='flashcard- 
 option'>{option}</div>
            })}
        </div>
    </div> 
    <div onClick={() => setFlip(!flip)} className='back' ref={backEl}>
        {flashcard.answer}        
    </div>
    
</div>

and then i render the NameForm inside my app.js function so that the form sits nicely above all the flashcard components:

import React, { useState, useEffect } from "react"
import FlashcardList from "./FlashcardList"
import './app.css'
import axios from 'axios' // makes importing from api easy
import NameForm from './NameForm'
import checkGuess from './Flashcard'
import flashcard from "./Flashcard"
import value from './NameForm'



export default function App() {
const [flashcards, setFlashcards] = useState([])

useEffect(() => {
    axios.get('http://127.0.0.1:5000/')
    .then(res => {
        setFlashcards(res.data.results.map((questionItem, index) => { // mapping over api to get 
objects "questionItem" and the index of each one
            const answer = decodeString(questionItem.correct_answer) // setting the 
correct_answer objects from api to answer
            const question = decodeString(questionItem.question)
            const options = [
                ...questionItem.incorrect_answers.map(a => decodeString(a)), answer // spreading 
incorrect_answers objects into an array with answer at the back to set all of them into options
            ]
            return {
                id: question, // sets the id to the index from the api and the exact time to make 
sure its always unique
                question: question, // setting question objects from api to question
                answer: answer, // already defined above
                options: options.sort(() => Math.random() - .5), // sorting all the options 
randomly
                user: value
            }
        }))
    })
}, [])

function decodeString(str) {
    const textArea = document.createElement('textarea')
    textArea.innerHTML= str
    return textArea.value // function brings all of our objects into this new element and decodes 
all of the encoded html
}



return (
    
       <div>
           <NameForm answer={flashcard.answer} checkGuess={checkGuess} />
            
            <div className="container">
                <FlashcardList flashcards={flashcards} />
            </div>
        </div>
)
}

how can i get the actual state value inside that component? any help is greatly appreciated ive been trying to figure this out for a while and i have trouble with lifting state.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source