Reputation: 2324
Currently I am working on Building Game of Life in FCC and I thought this would be a great project to test my knowledge on React-Redux.
Since I am a new to Redux, I am having difficulty to understand what is a dumb component vs a smart component in this project.
In my view, this is how I see:
NOTE: when I say "Smart Component" vs "Dumb Component" I simply mean that to be a "Smart Component" it is a container, or something that ties with the app's state, where as a "Dumb Component" simply means it's job is to simply render whatever it's being fed on.
If my assumption is correct, then I am having hard time to setup the app state correctly on the cells.
Here's what I've written so far:
component/board.js
import React, { Component } from 'react';
import Cell from '../containers/cell'
export default class Board extends Component {
constructor(props){
super(props);
this.state = {height: 18, width: 40}
this.test = this.test.bind(this)
}
test(){
console.log(this.state)
}
render(){
let rows = [];
for (var i = 0; i < this.state.height; i++){
let rowID = `row${i}`
let bin = []
for (var idx = 0; idx < this.state.width; idx++){
let cellID = `cell${i}-${idx}`
bin.push(<Cell key={cellID} id={cellID}/>)
}
rows.push(<tr key={i} id={rowID}>{bin}</tr>)
}
return(
<div className="container">
<div className="row">
<div className="col s12 board"></div>
<table id="simple-board">
<tbody>
{rows}
</tbody>
</table>
</div>
</div>
)
}
}
container/cell.js
import React, { Component } from 'react';
// import from '../actions/index';
// import { connect } from 'react-redux';
// import { bindActionCreators } from 'redux';
export default class Cell extends Component{
constructor(props){
super(props);
this.state = {
color: 'dead'
};
this.test = this.test.bind(this);
}
test(){
this.state.color === 'dead' ? this.setState({color:'alive'}) : this.setState({color:'dead'})
}
render(){
return (
<td
className={this.state.color}
key={this.props.cellID}
id={this.props.cellID}
onClick={this.test}>
</td>
)
}
}
// function mapDispatchToProps(dispatch){
// return bindActionCreators({}, dispatch)
// }
// export default connect(null,mapDispatchToProps)()
I'm not sure how I can approach at this point. At first I thought about having to wrap all the cells in an array and that would be the app's state, but I am not sure how to go on about that.
Any response will be greatly appreciated
Upvotes: 1
Views: 269
Reputation: 1890
I would suggest that you make your hierarchy like this. I'm going to represent the component hierarchy as a JSON-like syntax just so that you can understand:
App (smart) {
dispatchProps: {
...gameControlActions, // gets passed into GameControls
onCellClick, // gets passed down to Board, and then to each Cell
}
stateProps: {
cells: [{
id: #
status: 'dead', // or 'alive'
}], // gets passed down to Board, to render cells
...generationData, // gets passed down to Generation
}
}
// Children of App
GameControls (dumb) // start, clear, randomize
Board (dumb)
Cells (dumb)
Generation (dumb)
When you render the Cells, you would render them like this:
<Cell key={cellID} id={cellID} status={status} onClick={this.props.onCellClick} />
Inside the Cell
component the render
function would look like this and you can now get rid of state
:
render(){
return (
<td
className={this.props.status}
id={this.props.id}
onClick={this.props.onClick.bind(null, this.props.id)}>
</td>
)
}
Your onCellClick
action would simply look like this:
function onCellClick(cellId) {
return {
type: 'CELL_CLICK',
payload: cellId,
};
}
You would then process that action in your reducer by toggling the status
of that cell in your cells array (remember to return a new copy of cells
). Also, and if necessary, you might need to make your Cell
component extend PureComponent
, in order to speed up the reconciliation process or to implement shouldComponentUpdate
.
Let me know if this doesn't make sense, or if you have questions (I think you will).
Upvotes: 2