-1

I have a unique situation in React/Next. Essentially, I am iterating in React to create divs. The iterating functionality works beautifully. I now am trying to create hide/show sections for each one of the created divs and I want to use the anchor tag to allow the hiding and showing of hidden divs. I followed [this][1] thread for the hiding element and [this][2] link for concatenating function names. However, I do not think the second link is applicable to concatenate function names in React as it says that showDogFunctions is not a function which is evidently not a good error. Can anyone help? Additionally, if anyone has more concise ways to achieve my functionality that would also be appreciated.


**Error**
Variable Names are a bit dif but you can easily associate.

[![Error][3]][3]


  [1]: https://stackoverflow.com/questions/24502898/show-or-hide-element-in-react
  [2]: https://stackoverflow.com/questions/23263601/concatenation-function-name-in-js
  [3]: https://i.stack.imgur.com/zUoxr.png
Juliette
  • 4,309
  • 2
  • 14
  • 31
  • 2
    The more usual way to do this would be to make the dog divs their own component which would then contain the show, toggle, etc relevant to just that item. – dezfowler Apr 17 '21 at 22:00
  • Code works fine, you just need to add initial `dogCounter` state greater than 0, like 3 to match your map lookups. See running [codesandbox](https://codesandbox.io/s/concatenating-function-names-reactjs-stackoverflow67143306-zed55). – Drew Reese Apr 17 '21 at 22:01
  • Can you please copy&paste the error? The error you are describing shouldn't happen with this code. – Christian Fritz Apr 17 '21 at 22:01
  • @christian with a bit of imagination, there is probably a button to increase dogCounter, and for dogCounter > 3 this fails ... – Jonas Wilms Apr 17 '21 at 22:13

1 Answers1

2

If you have a state for each component then the state should actually be in that component. As <div>s do not have state, you need a functional component around them:

 function SingleDog({ counter }) {
    const [show, setShow] = useState(false);

    return (
       <div key={counter} className="user-box">
         <span className="expand-more">
            <a onClick={() => setShow(it => !it)} >Toggle</a>
            {show && <div>Hi there</div>}
          </span>
        </div>
    );
 }

 function DogList() {
    const [dogCount, setDogCount] = useState(0);
   
   const dogs = [];

   for(let count = 0; count < dogCount; count++) {
      dogs.push( <SingleDog counter={counter} /> );
   }

   return <>
     {dogs}
     {/* ... more content here */}
   </>;
 }

If you need to influence the state of all components from the parent, e.g. close all expands, then you need to lift state up again. However instead of having n states, use one state with an array or object, e.g.:

  const [show, setShow] = useState({ });

     //...
     <SingleDog
      counter={counter}
      show={show[counter]}
      setShow={() => setShow(prev => ({ ...prev, [counter]: !prev[counter] }))}
     />
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151