skip to Main Content

Good day,

I´m learning React using function components and I have 2 components and the App.js file that look something like this:


App.js

import Container from './components/Container';
import InfoBox from './components/InfoBox';

function App() {


  return (
    <div>
      <InfoBox content='test info box content'/>
      <Container text='Charles Darwin' />
      <Container text='Alexander The Great' />
      <Container text='Nichola Tesla' />
      <Container text='Aristoteles' />
    </div>

  );
}

export default App;



Container.js

function Container(props) {
    return (
        <div className = 'containerDiv'>
            <p className = 'containerText'
              /*onMouseEnter={functionToChangeContent}
              onMouseLeave={functionToHideContent}*/  
            >
                {props.text}
            </p>
        </div>
    );
}

export default Container;


infoBox.js

function InfoBox (props) {
    return (
        <div className='infoBox'>
            <p>
                {props.content}
            </p>
        </div>

    );
}
export default InfoBox;

I want to change the content of the InfoBox component when hovering a Container component

What I wanna do it´s that so when I hover a the Container of a person in the website, the content of the InfoBox will change to show information about that person but for now I want to start with something little like just changing the content to the name of the person (the props.text of the Container) but I have just managed to do this by rendering the InfoBox into the Container component using functions with the onMouseEnter and onMouseLeave and states; but that means that the InfoBox doesn´t appear when entering the first time the page and will only exist after hovering for the first time a Container. Or by adding the "onMouseEnter/Leave" at every Container in the App.js but I feel it will be better to just do that in the Container module to make it more practical and easy to read.
(The "onMouseEnter/Leave" in the Container component are commented and point to no real function because that´s just a failed test I wanted to do but to show what I´m trying to achieve)

It´s there a better way to connect these components so I can render the InfoBox in the App.js but still change it´s content when hovering a Container?

2

Answers


  1. Try using react’s useState docs

    You can pass a parent’s set_foo funciton (from [foo, set_foo] = useSatate(default_value) to child components. The children can call set_foo which updates foo in the parent.

    In this case, we are only setting a string in the parent. However, you could set an object with more details for your use case, but I think this will lead you down the right path 🙂

    This is not the only way (and probably not the best way), but this could work, for exmaple:

    import React, { useState } from 'react';
    
    export function App(props) {
      const [name, set_name] = useState(''); // magic of useState !
      
      return (
        <div>
          <InfoBox content={`test info box content. Name: ${name}`}/>
          <Container text='Charles Darwin' set_name={set_name} />
          <Container text='Alexander The Great' set_name={set_name} />
          <Container text='Nichola Tesla' set_name={set_name}/>
          <Container text='Aristoteles' set_name={set_name}/>
        </div>
      );
    }
    
    function Container(props) {
        return (
            <div className = 'containerDiv'>
                <p className = 'containerText'
                  onMouseEnter={() => props.set_name(props.text)} // set
                  onMouseLeave={() => props.set_name('')} // clear
                >
                    {props.text}
                </p>
            </div>
        );
    }
    
    function InfoBox (props) {
        return (
            <div className='infoBox'>
                <p>
                    {props.content}
                </p>
            </div>
    
        );
    }
    

    Demo

    Login or Signup to reply.
  2. There are multiple ways to do this. You can maintain the state in the App.jsx and pass the getters and setters down the components via prop drilling. However the best way is probably to use React’s inbuilt context.

    React Context version (recommended)

    import * as React from 'react';
    
    const context = React.createContext(null);
    
    function InfoBox () {
      const { value } = React.useContext(context);
        return (
            <div className='infoBox'>
                <p>
                    {value}
                </p>
            </div>
        );
    }
    
    function Container(props) {
        const { setValue } = React.useContext(context);
    
        return (
            <div className = 'containerDiv'>
                <p className = 'containerText'
                  onMouseEnter={() => setValue(props.text)}
                  onMouseLeave={() => setValue("none")}
                >
                    {props.text}
                </p>
            </div>
        );
    }
    
    export function App() {
      const [content, setContent] = React.useState('none');
      return (
        <div>
          <context.Provider value={{ value: content, setValue: setContent }}>
            <InfoBox />
            <Container text='Charles Darwin' />
            <Container text='Alexander The Great' />
            <Container text='Nichola Tesla' />
            <Container text='Aristoteles' />
           </context.Provider>
        </div>
      );
    }
    

    Codesandbox demo here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search