Search code examples
javascriptcssreactjsemotion

Toggle between active content state


I'm building a React tab navigation component with emotion. I'm having trouble finding a solution that would allow me to:

  • Initially hide all content except for the buttons and not style the buttons.
  • When you click on a button activate the style and show the content associated with that button.
  • And finally when you click outside or the input is empty reset to initial state.

Here is the code: Code

import React, { useState } from "react";
import ReactDOM from "react-dom";
import styled from "@emotion/styled";

import "./styles.css";

const StyledShowButton = styled("button", {
  shouldForwardProp: (prop) => ["active"].indexOf(prop) === -1
})`
  color: ${({ active }) => (active ? "red" : "black")};
`;

function App() {
  const [active, setActive] = useState(0);
  const [showInput, setShowInput] = useState(false);

  const handleInputChange = (e) => {
    if (e.target.value < 1) {
      console.log("Reset Everyting");
    }
  };

  const handleTabClick = (e) => {
    const index = parseInt(e.target.id, 0);
    if (index !== active) {
      setActive(index);
    }

    if (!showInput) {
      setShowInput(!showInput);
    }
  };
  return (
    <div className="App">
      <StyledShowButton
        type="button"
        id={0}
        active={active === 0}
        onClick={handleTabClick}
      >
        First
      </StyledShowButton>

      <StyledShowButton
        type="button"
        id={1}
        active={active === 1}
        onClick={handleTabClick}
      >
        Second
      </StyledShowButton>

      {/* CONTENT */}
      {active === 0 ? (
        <input placeholder="First input" onChange={handleInputChange} />
      ) : (
        <input placeholder="Second input" onChange={handleInputChange} />
      )}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Just ask if I didn't make my self clear enough,

Thanks beforehand!

Erik


Solution

  • You can hide inpts in this way at first by assigning a null value to the active state. You can also initialize values ​​from 1 so that id and state state are not confused. I made the arrangements. You can review the code below.

    You can also view it from this link. Code:

    function App() {
      const [active, setActive] = useState(null);
      const [showInput, setShowInput] = useState(false);
    
      const handleInputChange = (e) => {
        if (e.target.value < 1) {
          setActive(null);
        }
      };
    
      const handleTabClick = (e) => {
        const index = parseInt(e.target.id, 0);
        if (index !== active) {
          setActive(index);
        }
        if (!showInput) {
          setShowInput(!showInput);
        }
      };
    
      return (
        <div className="App">
          <StyledShowButton
            type="button"
            id={1}
            active={active === 1}
            onClick={handleTabClick}
          >
            First
          </StyledShowButton>
          <StyledShowButton
            type="button"
            id={2}
            active={active === 2}
            onClick={handleTabClick}
          >
            Second
          </StyledShowButton>
          {/* CONTENT */}
          {active &&
            (active === 1 ? (
              <>
                <input placeholder="First input" onChange={handleInputChange} />
              </>
            ) : (
              <input placeholder="Second input" onChange={handleInputChange} />
            ))}
        </div>
      );
    }