Ad

Undefined Value For Initial State In ReactJS

- 1 answer

I'm still pretty new with ReactJS and now I ran into something which confuses me totally.

I've created a bunch of components which render a Bootstrap modal. Furthermore I fetch initial state parameters from the sever through the componentDidMount function. My component structure looks something like this:

<App>
  <Modal Lauch Button /> 

  <Modal>
   <Modal Header />
   <Modal Body />     <-- here's the problem
  </Modal>
</App>

and my initial state array is of the form (of course JSON encoded):

array:5 [▼
   ...
   ...
   "private" => true
   "files" => array:2 [▼
       1 => array:7 [▼
          "id" => 0
          "route" => "some route"
          ...
          ...
       ]
       2 => array:7 [▼
          "id" => 1
          "route" => "some other route"
          ...
          ...
       ]
   ]
]

and my (minified) React application like this:

<script type="text/babel">

    var L5fmModalBody = React.createClass({

        render: function() {

            return(
                <Modal.Body>
                    <Grid fluid={true}>
                        <Row>
                            {
                                this.props.files.map(function (file) {
                                    return <L5fmModalBodyFileContent id={file.id} route = {file.route} / >
                                })
                            }
                        </Row>
                    </Grid>
                </Modal.Body>
            );
        }

    });

    var L5fmModalBodyFileContent = React.createClass({

        render : function() {
            return(
                <Col xs={6} md={4} className="img-row">
                    <div className="thumbnail thumbnail-img">
                        <img key={this.props.id} src={this.props.route} />
                    </div>
                </Col>
            );
        }

    });

    var L5fmModal = React.createClass({

        getInitialState : function() {
            return {
                data : []
            };
        },

        componentDidMount: function() {
            $.ajax({
                url: 'L5fm/setInitialState',
                dataType: 'json',
                cache: false,
                success: function(data) {
                    this.setState({data: data});
                    console.log(data);
                    console.log(this.state.data);
                }.bind(this),
                error: function(xhr, status, err) {
                    console.error(this.props.url, status, err.toString());
                }.bind(this)
            });
        },

        render: function() {

            return(

                <Modal {...this.props} bsSize="large" aria-labelledby="contained-modal-title-lg">
                    <Modal.Header closeButton>
                        <div className="header-button-group">
                            some buttons
                        </div>
                    </Modal.Header>

                    <L5fmModalBody files={this.state.data.files} />
                </Modal>
            );
        }

    });


    var App = React.createClass({
        getInitialState: function() {
            return { lgShow: false };
        },
        render: function() {
            let lgClose = () => this.setState({ lgShow: false });

            return (
                 <Button bsStyle="primary" onClick={()=>this.setState({ lgShow: true })}>
                    Launch large demo modal
                 </Button>
                 <L5fmModal show={this.state.lgShow} onHide={lgClose} />
            );
        }
    });

    ReactDOM.render(<App />, document.getElementById("modal"));

</script>

Whenever I run the application I get following error:

L5fmModalBody_renderTypeError: this.props.files.map is not a function. (In 'this.props.files.map', 'this.props.files.map' is undefined)

If I console.log(this.state.data.files) in my <Modal> component, it also shows that this.state.data.files is undefined? Obviously I have not understood what is going on. I've also tried to fetch data with componentWillMount but this did not help either. What am I doing wrong?

Thanks!


UPDATE

I think I got a step further. The actual issue is not that this.set,state is null at the start, because after componentDidMount is called and the "new" states are set, the UI gets rendered again. Furthermore I found out that JSON apparently handles assoziative arrays as objects and I believe that I can't call map on an object.

Any ideas?

Ad

Answer

Thanks to Dhaval Patel I finally have the answer to this issue. The problem was not the null value of the initial state because when componentDidMount gets called the UI gets rendered again and receives the updated states from the server. The actual problem was that JSON treats associative arrays as objects and therefore I could not call a simple map.

I just changed

{
    this.props.files.map(function (file) {
        return <L5fmModalBodyFileContent id={file.id} route = {file.route} / >
    })
}

to

{
    Object.keys(object).map(
        function(d){
            return <L5fmModalBodyFileContent id={object[d].id} route={object[d].route} />
    })
}

where object = this.props.files and it works like a charm!

To avoid the error of the (at first) undefined object I've used

{this.state.data.length!=0 ? <L5fmModalBody files={this.state.data.files} />:null}

in the <Modal /> component.

Ad
source: stackoverflow.com
Ad