React js props undefined when passing state to another file

Viewed 68

I am trying to pass the toggleState value from my Sidebar.jsx as props to another file Screens.jsx, which toggles between displaying the homepage or displaying nothing based on the toggleState value. However, when I try to access the value of the props in Screens.jsx, it tells me the value is undefined.

Sidebar.jsx

import Screens from './Screens';
import {useState} from 'react';

function Sidebar() {
  const [toggleState, setToggleState] = useState(1);

  return (
    <div>
      <div
        onClick={() => setToggleState(1)}
      >
      </div>

      <div
        onClick={() => setToggleState(2)}
      >
      </div>

      <Screens toggleState={toggleState} />

    </div>
  );
};

export default Sidebar;

Screens.jsx

import { useState, useEffect } from 'react';
import Homepage from './homepage';

function Screens({toggleState}) {
  const [isActive, setIsActive] = useState(1);

  console.log(toggleState);

  useEffect(() => {
    setIsActive(toggleState);
  });

  return (
    <div style={{ height: 752 }}>
      { isActive === 1 ? <Homepage /> : null }
    </div>
  );
};

export default Screens;

Both Sidebar and Screens are imported in my Home.jsx. I'm not sure if this might be causing the issue.

Home.jsx

import Sidebar from '../components/sidebar';
import Screens from '../components/screens';

function Home() {
  return (
    <div>
      <div style={{ display: 'flex', width: 1200, height: 792 }}>

        <div style={{ width: 71, height: 792, marginTop: -42, marginLeft: -10, overflow: 'hidden' }}>
          <Sidebar />
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', width: 670, height: 752, backgroundColor: '#1e203c' }}>
          <Screens />
        </div>
      </div>
    </div>
  );
};

export default Home;
2 Answers

The useEffect hook is missing a dependency array to update the local state

useEffect(() => {
  setIsActive(toggleState);
}, [setIsActive, toggleState]);

But this is an anti-pattern in React, just consume the toggleState prop directly in the component.

function Screens({ toggleState }) {
  return (
    <div style={{ height: 752 }}>
      {toggleState === 1 && <Homepage />}
    </div>
  );
};

You are rendering the Screens component in two places, once by the Sidebar component and once again in the Home component. Lift State Up to the common parent component Home and pass down all the required props.

Example:

function Home() {
  const [toggleState, setToggleState] = useState(1);

  return (
    <div>
      <div style={{ display: 'flex', width: 1200, height: 792 }}>
        <div style={{ width: 71, height: 792, marginTop: -42, marginLeft: -10, overflow: 'hidden' }}>
          <Sidebar {...{ setToggleState, toggleState }} />
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', width: 670, height: 752, backgroundColor: '#1e203c' }}>
          <Screens {...{ toggleState }} />
        </div>
      </div>
    </div>
  );
};

Sidebar is passed both the setToggleState callback to attach to the div elements onClickhandler, andtoggleStateis passed along toScreens`.

function Sidebar({ toggleState, setToggleState }) {
  return (
    <div>
      <div onClick={() => setToggleState(1)}>
      </div>

      <div onClick={() => setToggleState(2)}>
      </div>

      <Screens toggleState={toggleState} />
    </div>
  );
};

Screens receives the toggleState prop as before.

function Screens({ toggleState }) {
  return (
    <div style={{ height: 752 }}>
      {toggleState === 1 && <Homepage />}
    </div>
  );
};

Edit react-js-props-undefined-when-passing-state-to-another-file

use the state from your Home file:

import Sidebar from '../components/SideBar';
import Screens from '../components/Screens';

function Home() {

const [toggleState, setToggleState] = useState(1);
  return (
    <div>
      <div style={{ display: 'flex', width: 1200, height: 792 }}>

        <div style={{ width: 71, height: 792, marginTop: -42, marginLeft: -10, overflow: 'hidden' }}>
          <SideBar setToggleState={setToggleState} />
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', width: 670, height: 752, backgroundColor: '#1e203c' }}>
          <Screens toggleState={toggleState} />
        </div>
      </div>
    </div>
  );
};

export default Home;

use the setState from the SideBar file to change the state and remove de Screens import:

function Sidebar({setToggleState}) {

  return (
    <div>
      <div
        onClick={() => setToggleState(1)}
      >
        one
      </div>

      <div
        onClick={() => setToggleState(2)}
      >
       two
      </div>

    </div>
  );
};

export default Sidebar;

is not nessesary use other state in Screen file:

import App from './App';

function Screens({toggleState}) {

  console.log(toggleState);

  return (
    <div style={{ height: 752 }}>
      { toggleState === 1 ? <App /> : null }
    </div>
  );
};

export default Screens;

but if you wat to use it, you have to say to your useEffect that the variable change:

...
useEffect(() => {
    setIsActive(toggleState);
  },[toggleState]);
...
Related