0

I have read:

ReactJs: How to pass the initial state while rendering a component?

ReactJS: Why is passing the component initial state a prop an anti-pattern?

Am still having trouble resolving this issue. Namely - rendering an array of child component declarations with props that rely on the initial state of the parent component.

I am new to reactjs and somewhat new to development. Any help would be appreciated.

boardCreation: function() {
    var board = [];
    for (var i = 0; i < 6; i+=1) {
        board.push(<Card key={i} onClick={this.onCardFlip} image={this.state.imagesArray[i]} flipped={this.flipped[i]} cardIndex={i} />);
    }; 
    return board;
},
getInitialState: function() {
    return {
        imagesArray: this.shuffledImages(['walle.jpg', 'walle.jpg', 'eve.jpg', 'john.jpg', 'captain2.jpg', 'mary.jpg']),
        flipped: [false, false, false, false, false, false],
        flippedImages: [],
        walleCount: 0,
        board: this.boardCreation(),
    }
},

The above returns 'Uncaught TypeError: Cannot read property 'imagesArray' of null'.

Initially I had the board creation in the render function of this parent component - however the board and all other states will need to reset every time a game ends and a new one begins.

Thank you.

Community
  • 1
  • 1
WallEBot
  • 41
  • 1
  • 6

1 Answers1

3

The issue is caused by the fact that you call this.boardCreation() in the getInitialState function. Therefore the initial state is not created yet, this is why you have null.

To fix this issue, you can simply refactor the code

boardCreation: function (images, flipped) {
    images = images || this.state.images;
    flipped = flipped || this.state.flipped;
    var self = this;
    return images.map(function (image, i) {
         return <Card key={i} onClick={self.onCardFlip} image={image} flipped={flipped[i]} cardIndex={i} />;
    });
},
getInitialState: function() {
    var images =  this.shuffledImages(['walle.jpg', 'walle.jpg', 'eve.jpg', 'john.jpg', 'captain2.jpg', 'mary.jpg']);
    var flipped = [false, false, false, false, false, false];
    return {
        imagesArray: images,
        flipped: flipped,
        flippedImages: [],
        walleCount: 0,
        board: this.boardCreation(images, flipped),
    };
}

I would also suggest to refactor your code in a more OOP fashion: You could have a card object, holding the attributes image, flipped, index, etc.

gcedo
  • 4,811
  • 1
  • 21
  • 28
  • Thank you for the suggestions and re-factoring - your code presents **Uncaught SyntaxError: missing ) after argument list** for the images.map function call even if I include another bracket to `return images.map((image, i) => { return ( )})` – WallEBot Jun 08 '15 at 20:57
  • Are you transpiling to ES5? – gcedo Jun 08 '15 at 21:15
  • Not sure - using `jsx --watch src/ build/` – WallEBot Jun 08 '15 at 21:21
  • Ok, then you are not. I have rewritten in ES5. – gcedo Jun 08 '15 at 21:24
  • Now `this.onCardFlip` is having a similar issue. I would have to create 'temp' values for state values in other functions it seems. For example in `onCardFlip` which needs to read state I would have to create a `flipped = flipped ||...` there as well – WallEBot Jun 08 '15 at 21:50
  • **Uncaught TypeError: Cannot read property 'onCardFlip' of undefined** – WallEBot Jun 08 '15 at 22:09
  • `self.this` works for onCardFlip but not for flipped **Uncaught TypeError: Cannot read property '0' of undefined** – WallEBot Jun 08 '15 at 22:19
  • Images are not working now in the Child component as `this.props.image` so when clicking the Card the image does not change. Will have to see what is going on there now but you did solve this specific error and helped me think about restructuring so checkmark - thank you. – WallEBot Jun 08 '15 at 22:31
  • Have taken a closer look at restructuring in a more OOP approach as well into ES6 and Babel - thanks again for all the help - I do not yet have the ability to upvote but will come back and do so when possible. :) – WallEBot Jun 09 '15 at 00:52