Alejandro Alejandro - 3 months ago 19
React JSX Question

Simple background-color change in React-Redux

I essentially finished with one of FCC's project (https://www.freecodecamp.com/challenges/build-a-camper-leaderboard)

The only customization is that I'd like is for the user to see what the table is ordered from (either recent or alltime best scores).

Currently I have it with jQuery telling to change the header table css-attribute directly when the user clicks either the recent or alltime column, but I do not feel this is the right way.

Here's my container code which holds essentially the table itself

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'
import { recentData } from '../actions/index'
import { allTimeData } from '../actions/index'

export default class TableBoard extends Component {
constructor(props){
super(props);
}
componentDidMount() {
//Is there better way to initialize the background-color???
$("#col-recent").css("background-color", "lightblue");
this.props.recentData() //fetch data most recent top
}
renderData(userData,index){
const FCC_URL = 'https://www.freecodecamp.com/'
const img = userData.img
const name = userData.username;
const recent = userData.recent;
const allTime = userData.alltime;
return(
<tr key={name}>
<td className="rank">{index + 1}</td>
<td>
<img className="img-responsive"
src={img}
alt='FCC profile'
/> <a href={FCC_URL + name}>{name}</a>
</td>
<td className="recent">{recent}</td>
<td className="all-time">{allTime}</td>
</tr>
)
}
getRecentData(){
$("#col-recent").css("background-color", "lightblue");
$("#col-alltime").css("background-color", "#e2e2e2");
this.props.recentData()
}
getAllTimeData(){
$("#col-alltime").css("background-color", "lightblue");
$("#col-recent").css("background-color", "#e2e2e2");
this.props.allTimeData();
}
render(){
return(
<table className="table table-hover table-striped table-bordered">
<thead>
<tr>
<th className="rank">#</th>
<th className="username">Camper Name</th>
<th id='col-recent'className="recent clickable"
onClick={this.getRecentData.bind(this)}
>Points in 30 days
</th>
<th id='col-alltime' className="all-time clickable"
onClick={this.getAllTimeData.bind(this)}
>All-time Posts
</th>
</tr>
</thead>
<tbody>
{this.props.FCCData.map(this.renderData)}
</tbody>
</table>
)
}
}
function mapStateToProps(state){
return {
FCCData: state.collectData
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({ recentData, allTimeData }, dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(TableBoard);


I am still new to React-Redux so the paradigm of state is still new to me.

Answer

You can use React's state functionality to achieve this. So in you're componentDidMount(), or getRecentData() etc, you can do this:

componentDidMount() {
    this.setState({ bgColorRecent: 'lightblue' });
}

Then in render you respond to the state with react's inline styles functionality:

render() {
    const recentStyles = {
        backgroundColor: this.state.bgColorRecent || '',        
    };

    return(
        <table className="table table-hover table-striped table-bordered">
           <thead>
              <tr>
                 <th className="rank">#</th>
                 <th className="username">Camper Name</th>
                 <th style={recentStyles} id='col-recent' className="recent clickable" onClick={this.getRecentData.bind(this)}>
        {/*  the rest of your render * /}
    )
}

To set default state most people use the constructor:

constructor() {
    super();
    this.state = { bgColorRecent: 'black' };
}

If you don't set state in the constructor then this.state will be undefined until you call setState in the componentDidMount function, which means it'll be undefined in the first render. Requiring annoying protection:

const recentStyles = {
    backgroundColor: (this.state || {}).bgColorRecent || '',        
};

It's best to set a default state for any state prop that's referenced in your render function.

You definitely are correct in assuming that using jQuery to do this is a bad idea. React allows you to interact with a virtual DOM and it updates the actual DOM strategically based on changes in the virtual DOM. It keeps references in the actual DOM to do this efficiently. This is one reason React is so fast and efficient as scale. Because of this, if you start changing the actual DOM with jQuery you can cause a number of different problems. Whenever you need to interact with the DOM you want to do things the React way to take advantage of all it's power.

Comments