I am trying to build a tic-tac-toe game using class to practice passing the props to child components and lifting up the state of component that's why you can see my creating 4 components.
The problem I need help with is so that when I click one of the buttons all buttons change their value at the same time.
I need to make each button display its own value separately. I declared a function and gave it functionality to change the state from null to X or O.
// App component
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<>
<Board />
</>
);
}
}
// Board component
class Board extends React.Component{
constructor(props){
super(props);
this.state = {txt: 'X'};
this.change = this.change.bind(this);
}
change(){
const updt = (this.state.txt === 'X' || this.state.txt === '0') ? 'O' : 'X';
this.setState({txt: updt});
}
render() {
return(
<>
<div>
<Row key={'1'} value={this.state.txt} change={this.change}/>
<Row key={'2'} value={this.state.txt} change={this.change}/>
<Row key={'3'} value={this.state.txt} change={this.change}/>
</div>
</>
)
}
}
// Box component
function Box(props){
return (
<>
<button className='class1' onClick={props.change} >{props.value}</button>
</>
);
}
// Row component
function Row(props){
return (
<>
<div id='myId'>
<Box change={props.change} value={props.value}/>
<Box change={props.change} value={props.value}/>
<Box change={props.change} value={props.value}/>
</div>
</>
)
}
ReactDOM.render(<App/>, document.querySelector('#root'));
all of your button change text because you literally passing them the same value, instead you need to create an array of rows each row contains an array of buttons, and then you map over these array like I'm down down below, that's how things are meant to be don in react. I also added a user turn functionality.
// App component
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<>
<Board />
</>
);
}
}
// Board component
class Board extends React.Component{
constructor(props){
super(props);
this.state = {
turn:"X",
rows:[
//ROW 1
[
{
id:"btn1",
text:"0"
},
{
id:"btn2",
text:"0"
},
{
id:"btn3",
text:"0"
},
],
//ROW 2
[
{
id:"btn1",
text:"0"
},
{
id:"btn2",
text:"0"
},
{
id:"btn3",
text:"0"
},
],
//ROW 3
[
{
id:"btn1",
text:"0"
},
{
id:"btn2",
text:"0"
},
{
id:"btn3",
text:"0"
},
],
]};
this.change = this.change.bind(this);
}
change(rowIndex,btnId,btnLastValue){
const updt = (btnLastValue === 'X' || btnLastValue === '0') ? 'O' : 'X';
let tempState= [...this.state.rows]
const targetBtn= tempState[rowIndex].filter(btn=>btn.id==btnId)[0]
const targetBtnIndex= tempState[rowIndex].indexOf(targetBtn)
let updateText = this.state.turn=="X" ? "X": "O"
const tempState[rowIndex][targetBtnIndex].text= updateText
this.setState({...this.state,rows: tempState, trun:updateText });
}
render() {
return(
<>
<div>
{
this.state.rows.map((row,index)=><Row
key={index}
rowIndex={index}
row={row}
change={this.change}
/>
)
}
</div>
</>
)
}
}
// Box component
function Box(props){
const {value,rowIndex,change}=props
return (
<>
<button className='class1' onClick={e=>change(rowIndex,value.id,value.text)} >{props.value}</button>
</>
);
}
// Row component
function Row(props){
const {row,rowIndex,change}=props
return (
<>
<div id='myId'>
{
rows.map(btn =><Box
change={change}
rowIndex={rowIndex}
value={btn}
/>)
}
</div>
</>
)
}
ReactDOM.render(<App/>, document.querySelector('#root'));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.