0

I'm new to React. As a learning exercise I'm building an chess application

I want to change the DOM of child based on state in parent. Currently there is no change in child components on change of state in parent.

Parent Component

class Game extends Component{
    constructor(){
        super();
        this.state = {
            game :{ 
                board_position = { 'One' : ''}
            }
        }

        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(){
        let p = this.state.game.board_position;

        // some computations on p
        p = { board_position : { 'One' : Math.random() } }

        this.setState({
            game : p
        })

        //this.forceUpdate(); // Just trying different methods to make it work
    }

    render(){
        return(
            <div onClick={(e) => this.handleClick(e) }>
                <Piece {...this.state.game.board_position} />
            </div>
        )
    }
}

Child Component

Class Piece extends Component{

    constructor(){
        super(props);
        this.state = {
            clr : ''
        }
    }

    componentWillMount(){
        let c;

        // some computations that change value of c based on props
        if( typeof ( this.props.game.one) == number ){
            c = 'Red'
        } else {
            c = 'Blue'
        }


        this.setState({
            clr : c
        })

    }

    render(){
        return(
            <span>{this.state.clr}</span>
        )
    }
}

On call of handle click method, there is a change in state of the game. However, subsequent changes in Child are not seen.

Can anyone please help me out? Where am I going wrong?

I'm not sure how to implement ref as suggested over here. However, I don't think that is a good solution. Probably I'm having some conceptual misunderstanding.

PS: Please ignore any syntax error. This code is a strip down of real code. If you want to take a look at full code - go over here

  • There are so many weird things going on here. You shouldn't be force-updating. Setting state should care of that for you. Also, never mutate state directly. You've misspelled `constructor` and don't have braces around `this.state.clr`. You're not using the props you pass from the parent, and `componentWillMount` runs once... thus no change occurs after first render – Andrew Li Dec 06 '17 at 02:52
  • Hi, As I said, Please ignore syntax errors. This is strip down version of code and not the real code itself. I've also given the link to real code – Siddharth Patel Dec 06 '17 at 03:00
  • 1
    It's your job to provide a [mcve]. No one will comb through your code for you. Isolate the problem yourself and provide a *complete* example without syntax errors. – Andrew Li Dec 06 '17 at 03:03
  • you're not using the props that are being passed by the parent component – JJJ Dec 06 '17 at 03:13
  • I'm using prop to make some calculation. Value of variable C will depend on value of props. But not using props directly – Siddharth Patel Dec 06 '17 at 03:16
  • Your code block has syntax issues it is better to post a code with minimum errors – Shashith Darshana Dec 06 '17 at 06:19

3 Answers3

0

componentWillMount in your Piece component will only fire once.

Are you updating your state each time the props change as well ? For example using componentWillReceiveProps

Also you could just display the props directly in your render function

render(){
    return(
        <span>{use the props directly here}</span>
    )
}

Try to avoid using state whenever possible, and stick with just rendering your component based on props.

klugjo
  • 19,422
  • 8
  • 57
  • 75
  • Thanks for your reply. I cannot use props directly, Since I need to make some calculations and use the calculated value – Siddharth Patel Dec 06 '17 at 03:22
  • You need to do the calculations each time the props change don't you ? Anyways, don't do the calculations in your component, do them in a Higher Order component or a state management system but only use your React components to display data. React is a view engine not a calculation engine. – klugjo Dec 06 '17 at 03:26
  • I understand. But those calculations will determine what is to be rendered in output – Siddharth Patel Dec 06 '17 at 03:28
  • Do the calculations in your render method and don't save anything in the state of `Piece` – klugjo Dec 06 '17 at 03:30
0

it's a pretty basic react process:

class Game extends Component{
    constructor(){
        super();
        this.state = {
            game :{ 
                 board_position = { 'One' : ''}
             }
        }

        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(e){
        let p = this.state.game.board_position;

        // some computations on p
        p = { board_position : { 'One' : Math.random() } }

        this.setState({
            game : p
        })
    }

    render(){
        return(
        <div onClick={this.handleClick}>
            <Piece board_position={this.state.game.board_position} />
        </div>
        )
    }
}

Child: //can be a function instead of a class

const Piece = ({board_position}) =>{
  const {board_position} = this.props;
  let clt = board_position;
  //do some stuff

  return(
    <span>{board_position}</span>
  );
};

if you want to do more calculations you can use componentWillReceiveProps(newProps)

TacoEater
  • 2,115
  • 20
  • 22
0

A component re render when it's props or states get changed. There will be certain life cycle methods get invoked based on the values of props and own states.

The way you accessed your **props is wrong.** It should be

this.props.One

Life cycle method you should have used is componentWillReciveProps(nextProps). In that case you should access the relevant prop like below

nextProps.One

I have created a working fiddle (your code had errors if you fixed those and looked at your log you could have easily figure out where the error is)

Shashith Darshana
  • 2,715
  • 1
  • 25
  • 27
  • componentWillMount will only be called once, so the game won't change when the o game prop changes. – TacoEater Dec 06 '17 at 14:04
  • 1
    sorry. Constructor is called once. componentWillMount will be called every time the component is going to update. But yes I used the wrong life cycle method. It should be componentWillReceiveProps. And I have updated my answer now. – Shashith Darshana Dec 06 '17 at 17:13