javascript – Conditionally rendering an array within an array within the return statement?-ThrowExceptions

Exception or error:

I’ve tried many of the methods outlined by other users, but no dice. I’m not sure what I’m doing wrong.

Essentially, I’m referencing idNumbers, an array of booleans (initialized to false), with each index corresponding to a different instance of a “file” object. I want to access this array and use the boolean held at each index to determine if the content in file should be rendered or not. My onClick() calls a function that toggles the boolean at whatever index is passed to it.

Right now, I’m displaying the button just fine, but the content will show regardless. Clicking the button doesn’t do anything. I’m not using a simpler method because I don’t know how many file objects there are, and so it has to be dynamic.

The return statement, which is inside of a Results component (which pulls from the Content component):

return(
   <div>
       {content.fileInfo.map(file => 
           <div>
               <button className="button" onClick = {toggleFile(file.id)}> 
                    {file.title} 
               </button>
               {content.idNumbers[file.id] && (<div>{file.content}</div>)}
           </div>
        )}
       {content.someOtherStuff}
   </div>
);

The bool array, returned from the content component:

const idNumbers = []; 
idNumbers.push(false); //sample. this was done in a .map, though.

My toggleFile function:

const toggleFile = (id) => {
      content.idNumbers[id] = !content.idNumbers[id];
};

I’ve been messing with this for hours. Please let me know what I can change so I can get this working. I’m aware this isn’t an elegant solution either way, but I’m just trying to get the bare bones working. Thank you.

EDIT: figured I should clarify…{file.content} is itself an array.

EDIT2: the file object, which is made within a .map(file,index) and added to an array of files:

fileObj = { 
    title: {file.title},
    id: index, 
    content: [] 
};
How to solve:

You need to trigger a re-render. This is done by calling setState() or this.forceUpdate() .

I can’t tell where your contents is coming from (i.e. props, state, or somewhere else) but you should not be modifying it directly if its a prop. Instead, you should notify the parent component that something has happened via a callback (and let the parent component modify the data at its source). This is referred to as a controlled component. The other option is to handle it internally via state. This is an uncontrolled component. You see it a lot with form controls.

setState requires that state actually change. You can do this by increasing a counter or actually changing internal data. If you aren’t storing data internally, I find setState + a counter to be annoying and instead just rely on forceUpdate

If you are using React Hooks, I believe you are forced to use setState and a counter. Except it would look something like

let [counter, setCounter] = useState(0);

// Inside click method
setCounter(counter + 1);

Leave a Reply

Your email address will not be published. Required fields are marked *