5

I am trying to add className value to list items. I map through an array of objects, and depending on the value of 'name' in the object, a differenct class would be added.

Specifically, I am trying to make a message app, if the user is 'You', the message would have class 'right' and the message is shown on the rihgt of the screen. If the user name != 'You', then the className 'left' should be given.

I've tried adding an if statement within the render part of the code, and also within the sendMessage() function to add the class when pushing the message into the array (before it is even shown on the screen). All I get are syntax errors. Please advise...

import React, { Component } from 'react';

class LandingPage extends Component {
  constructor(props) {
    // When you pass props to super, the props get assigned to 'this'
    super(props);
    // this.state is the buildiing block of the data that gets used
    this.state = {
      message: '',
      name: '',
      list: []
    }
  }

  updateInput(key, value) {
    // update react state with input data
    this.setState({
      [key]: value
    })
  }

  sendMessage() {
    const newMessage = {
      message: this.state.newMessage,
      name: 'You'
    }

    const list = [...this.state.list];

    list.push(newMessage);

    this.setState({
      list,
      newMessage: ''
    })
  }

  render() {
    return <div className='container'>

      {/* messages will be listed here */}
      <div className='messagesDiv'>
        <ul>
          {/* List array is mapped through*/}
          {this.state.list.map(item => {
            return (
              <li className={item.class}>
                {item.name}: {item.message}
              </li>
            )
          })}
        </ul>
      </div>

      {/* message text area and send button here  */}
      <div className='inputDiv'>
        <form>
          <input type='text' className='input'
            value={this.message}
            onChange={e => this.updateInput('newMessage', e.target.value)}
          />
          <button className='btn btn-primary'
            onClick={() => this.sendMessage()}>Send</button>
        </form>
      </div>

    </div>
  }
}
export default LandingPage;

So above where it has {item.class}, this should either be 'right' or 'left'.

I've left just the code I think you'd need to see to diagnose my problem/ offer a solution.

Thanks.

jesusWalks
  • 355
  • 4
  • 16
  • Which syntax errors you get and in which position? – Dmitry Reutov Nov 13 '19 at 09:42
  • I tried adding an if statement in within the 'return' of the component and also in the sendMessage function. I get red lines all over the code, includes message of unresachable code detected, expression expected, etc. Nothing that crashes or blocks compilation of the app on local server, but no positive result. – jesusWalks Nov 13 '19 at 09:49

4 Answers4

3

You could use a simple function like this:

function userToClass(user){
   var userClass = '';
   if(user === 'You') {
      userClass = 'left';
   }
   else 
      userClass = 'right';
   }

   return userClass ;
}

and then use it like this:

return (
          <li className={userToClass(item.name)}>
            {item.name}: {item.message}
          </li>
        )
UnclePetros
  • 185
  • 10
  • Excellent. A correct answer. Thank you.I was trying so hard to get this logic within the code but that was wrong. Your solution is simple but effective - I wish I though of it! – jesusWalks Nov 13 '19 at 10:04
  • 1
    If you want a shorter code you can use ternary operator directly in your className attribute like this: className = {(item.name === 'you' ? 'left' : 'right ')} – UnclePetros Nov 13 '19 at 10:06
  • That's even better. Thank you. – jesusWalks Nov 13 '19 at 10:08
2

Just adding a simple ternary operator will do the trick. Have a look at the example below -

{this.state.list.map(item => {
  return (
    <li className={item.name === 'You' ? 'float-left' : 'float-right'}>
      {item.name}: {item.message}
    </li>
  )
})}
dbigpot
  • 410
  • 4
  • 11
0

let's assume you have a set of classes derived from your business logic, in that case, it's pretty simple.

<MyComponent className={React.addons.classSet(classes)} />;

or you can do

 <MyComponent className={classNames.join(' ')} />;
Moshiour
  • 633
  • 7
  • 20
  • But the list will have an either/or, depending on the value of 'name' within the object being printed on the screen – jesusWalks Nov 13 '19 at 09:46
  • then you can create that array of classes before applying it into the component. – Moshiour Nov 13 '19 at 09:48
  • But that still leaves the question of where to put the if statement, or how how to assign one of two potential classes to a dynamically produced list element. How? – jesusWalks Nov 13 '19 at 09:51
  • 1
    create a function that will return the list of classes ses based on your logic. Reac.addons.classSet(yourFunction(params)) – Moshiour Nov 13 '19 at 09:55
0

In NextJs you can try like this:

{popup_links.map((link, i) =>(
            <a
              key={link.title + i}
              href={link.href}
              className={`${styles.button} ${styles[link.customClassName]}`}
              onClick={(e) => {
                // your data
              }}
            >
              {link.title}
            </a>
          ))}

and link.customClassName is your custom class from json.

enter image description here

Elisei Nicolae
  • 293
  • 2
  • 12