0

I constantly have issues trying to use code and material-ui elements in react jsx code. Here's a code snippet:

const icols = 0;
const makeTableRow = (
  x,
  i,
  formColumns,
  handleRemove,
  handleSelect) =>
  <TableRow key={`tr-${i}`}>
    {formColumns.map((y, k) => (
      y.displayColumn ? (<TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>) : null), <-comma added for next line
      y.displayColumn ? (cols+=1) : null)
    )}
    <TableCell>
      <IconButton onClick={() => handleSelect(i)} ><EditIcon fontSize='small'/></IconButton>
      <IconButton onClick={() => handleRemove(i)} ><DeleteForeverIcon fontSize='small' /></IconButton>
    </TableCell>
  </TableRow>

I am getting a jsx parsing error, when I add this line above:

      y.displayColumn ? (cols+=1) : null)

If I remove the comma at the EOL above it, I still get an error. Basically I can't get a map to exec more than one statement.

If I take out the line and the EOL comma above it, everything works but I don't get a displayed column count, which I require.

I've tried using simple if/else which I am more comfortable with, but I have NEVER been able to get if/else to work in a jsx function. I want to only create a tablecell for a column w/displayColumn flag set to true, and I want a total count of the displayed columns, so I can use it later on (cols).

Is there a way to accomplish this with an if/else statement? Then I can have more than 1 statement in the if clause. The ternary operator only allows 1 statement, and I can't find anywhere what maps limitations are.

Thanks in advance for your help!

1
  • try this: {formColumns.map((y, k) => { y.displayColumn ? (cols+=1,return <TableCell key={trc-${k}}>{x[y.name]}</TableCell>) : return null)} )} Commented Jul 6, 2020 at 4:50

3 Answers 3

1

You can do something like this. You can open the open the arrow function body in map and put return JSX and do the cols increment there. Instead of having two ternary operator checks for the same condition, we can have just one conditional statement.

<TableRow key={`tr-${i}`}>
  {
    formColumns.map((y, k) => {
      if (y.displayColumn) {
        cols += 1;
        return <TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>
      }
      return null
    })
  }
  <TableCell>
    <IconButton onClick={() => handleSelect(i)} ><EditIcon fontSize='small'/></IconButton>
    <IconButton onClick={() => handleRemove(i)} ><DeleteForeverIcon fontSize='small' /></IconButton>
  </TableCell>
</TableRow>
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks abito. That worked. I swear I tried the exact same thing but got an error. Perhaps because I used an else statment? Or did not use a return? I really want to understand this because I keep running across the same kind of issues.
Happy to help. This can be confusing sometimes, If you want to have multiple statements inside map, you should have a function body enclosed with curly brackets and have a return statement inside. If it is conditional return, always provide one default return.
I'm having the same kind of issue here, trying to insert js code amongst material-ui elements: stackoverflow.com/questions/62751068/…
1

Basically I can't get a map to exec more than one statement.

You can't execute more than one expression inside a arrow function definition, instead use regular declarated functions

    {formColumns.map((y, k) => {
      y.displayColumn ? (cols+=1) : null;
      // Return what you want to render
      return y.displayColumn ? (<TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>) : null
    }}

There are only two types of arrow function

arrow_function = () => "i will be returned"
// This way you declare only one expression after the arrow and it is returned

and

arrow_function = () => {
    // This is a regular logic function
    text = "i will be" + " returned";
    return text;
}

EDIT 1: Add conditionals between JSX

There are two ways i know to do it

const App = () => {
  return (
    <div>
      <h2>First form</h2>
      <FirstForm true={true} />
      <hr />
      <h2>Second form</h2>
      <SecondForm true={false} />
    </div>
  )
}

const FirstForm = props => {
  // This way is just a ternary conditional
  return (
    <div>
      {props.true
        ? <span className="success">True condition matched</span>
        : <span className="danger">False condition matched</span>
      }
    </div>
  )
}
const SecondForm = props => {
  // This way uses a anonymous function executed in runtime
  return (
    <div>
      {(() => {
        let message = "Hello";
        message += " World, from an auto executed anonymous function";
        return (
        <span className={props.true?"success":"danger"}>{message}</span>
        )
      })()}
    </div>
  )
}

ReactDOM.render(
  <App />,
  document.getElementById("react")
);
.success {
  color: darkgreen;
}
.danger {
  color: #5e181b;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


<div id="react"></div>

3 Comments

This shows me what I can't do, which I appreciate. But I've tried to use normal javascript functions. When I do I get errors when I try to include material-ui elements in it. Can you SHOW me what would work? I can't get if/else statements to work w/material-ui elements.
@aaava you mean you want if/else statements inside jsx? It's posible.
Well, if it is, I have not been able to find any examples of this on the web. I have another question with the same kind of issue, where I cannot add any javascript statements to a set of material-ui elements. No matter HOW I frame it, I get syntax errors. After 20 years of C# and Java, one would think this wouldn't be so difficult! Even the answer above only has an if statement. Whenever I try to add an 'else' I get an error.
0

Ok psiro, so I looked at your examples, which all work in your situation. However, as soon as I apply one to my scenario, I still get a syntax error. Like here:

<TableBody>
  {(() => {
    console.log('data = ' + JSON.Stringify(data, null, 2) + '.'));
    return ((data.length > 0) ? (
    data.map((x, i) => row(
    x,
    i,
    formColumns,
    handleRemove,
    handleSelect,
    editIdx
    ))) : (<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>) )
  })()}
</TableBody>

And this is the problem I have w/anonymous functions. They create unmaintainable code. I am not doing anything different than your example. Just TWO js statements inside the code you presented. Your code works, mine returns a syntax error.

And why do I even NEED a double-anonymous function to have 2 simple js statements inside an if statement? Why does your code work, and mine not?

Addendum:

Ok, so I made some inferences based on your code and realized I had added yet ANOTHER anonymous function (the map statement) into the code. I reworked it into this, which compiled:

  {(() => {
    console.log('data = ' + JSON.Stringify(data, null, 2) + '.');
    if (data.length > 0) {
    return (data.map((x, i) => row(x, i, formColumns, handleRemove, handleSelect, editIdx)))
  }
  return(<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>)
  })()}

The fact that it looks completely unmaintainable is irrelevant I guess. But it doesn't matter because it STILL doesn't work! Now I get a 'JSON.stringify is not a function' at runtime, which is ridiculous of course. Why can't I get a simple console.log to work in reactjs?

ADDENDUM:

Ok, I fixed the issue thanks to all the help. For anyone else that has an issue w/multiple statements inside an anonymous function, if you want to do it, you need to add a return statement so the function knows what result to return.

<TableBody>
  {(() => {
    console.log('data = ' + data + '.');
    if (data.length > 0) {
    return (data.map((x, i) => row(x, i, formColumns, handleRemove, handleSelect, editIdx)))
  }
  return(<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>)
  })()}     
</TableBody>

That includes when you have an anonymous function inside another anonymous function. Hope this helps anyone else having this problem.

2 Comments

tbh i never had any issue handling these things, i'd need to more context and play with the code to see why it doesn't work. Also it's probably a typo but your code says JSON.Stringify instead of JSON.stringify
Yeah, it was a typo when copying it. Wasn't in the code like that. I truly appreciate your help w/this. I'm just not a big fan of anonymous functions. I think they make code more difficult to maintain, but I'm obviously in the minority! If vscode were had better support for locating matching parens/curly brackets/etc it would probably help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.