NONAMA
NONAMA

Reputation: 523

React setState is null

I can't undestand how I can pass the information between two pages? I'm using react router and can pass id through a link and take correct string from array. That looks like this:

//my array

var data = [
      {id: 1, title: "Breaking News #1", text: "This is one test new", date: "12.05.2015"},
      {id: 5, title: "Breaking News #2", text: "This is *another* test new", date: "03.05.2015"}
    ];

//my fetch function

componentDidMount: function() {
        var id = this.props.params.id;
        var dt = data;
        var post = [];
        for (var i=0; i<dt.length; i++){
            if (dt[i].id == id){
                post.push(dt[i]);
            };
        };
        this.setState({post : post});
    },

And after that I'm trying to map all info using function this.state.post.map(function (p) { and have an error Uncaught TypeError: Cannot read property 'post' of null

As I understood my state is null. But why?

UPDATE:

To clarify my problem I want to share some code, of course!

First of all, I have an array 'data', as I said before. Next step - Route (by React Router) to pass id through two pages:

var routes = (
  <Route path="/" handler={NewsApp}>
    <DefaultRoute handler={NewsList}/>
    <Route name="id" path=":id" handler={SinglePostBox}/>
  </Route>
);

So now I have SinglePostBox component with data and id. In this component I do next things:

var SinglePostBox = React.createClass({
    componentDidMount: function() {
        var id = this.props.params.id;
        var dt = data;
        for (var i=0; i<dt.length; i++){
            if (dt[i].id == id){
                post.push(dt[i]);
            };
        };
        this.setState({post : post});
        console.log(this.state);
    },
    render: function(){
    return(
    <div className="readiv">
        <SinglePost />
        <CommentBox />
    </div>
    );
    }
});

And now I have only one string from data, which matched with id and had been pushed inside 'post' array. And after that I want to use post array in to map this string to different divs. But in my case I have console.log(this.state) = null.

I'm sorry, if I have a stupid mistake, I'm trying to use React only third day.

Upvotes: 1

Views: 10335

Answers (2)

NONAMA
NONAMA

Reputation: 523

Finally I found a solution for my case.

First of all as I understood, in my case I use Parent\Child system. So, as it says in docs, I need to pass props to communicate parent-child. So I dicided to do this:

var SinglePostBox = React.createClass({
    render: function(){
        var post = [];
        var id = this.props.params.id;
        for (var i=0; i<data.length; i++){
            if (data[i].id == id){
                post.push(data[i]);
            };
        };
    return(
        <div className="readiv">
            <SinglePost p={post}/>
            <CommentBox />
        </div>
    );
    }
});

And in a child component I did this:

var SinglePost = React.createClass({
    getInitialState: function () {
        return {p: this.props.p};
    },
    function() {console.log('A');},
    render: function(){
        return(
            <div>
            { this.state.p.map(function (news) {
                    return (
                    <div className="col-lg-12 mrg" key={news.id}>
                        <h3 className="ui top attached header">
                            <a>{news.title}</a>
                            <div className="rght">
                                {news.date}
                            </div>
                        </h3>
                        <div className="ui green attached segment">
                            {news.text}
                        </div>
                    </div>)
                })
                }
            </div>
        );
    }
});

So at the bottom line I have a full array with all info, I took only one string with correct id and passed it as a prop from parent to child. I don't actually sure about code. Maybe it's too complicated and I can use more convenient way. But now it works.

Thanks, @fuubah!

Upvotes: 0

svenhornberg
svenhornberg

Reputation: 15756

I think you need to create an inititalState. An empty {} object should be okay.

May have a look into the https://facebook.github.io/react/docs/component-specs.html#component-specifications and https://facebook.github.io/react/docs/component-specs.html#lifecycle-methods

object getInitialState() Invoked once before the component is mounted. The return value will be used as the initial value of this.state.

I am doing something like this

var data = [
      {id: 1, title: "Breaking News #1", text: "This is one test new", date: "12.05.2015"},
      {id: 5, title: "Breaking News #2", text: "This is *another* test new", date: "03.05.2015"}
    ];

getInitialState() {
        return this.data;
},

and then make your logic in your componentDidMount. Then the state should not be null.

Try to console.log(this.state) in your render method. To see if the state is null or just your post propertie.

You should look at a Flux implementation (https://github.com/voronianski/flux-comparison) and store your state in a store, so you can listen from your pages to this store. That way you can share data between pages. But as a sidenote I personally find it easier to have one store (and one state) for each page, and the other information are passed through properties. hope this helps.

Update:

Sometimes this it not your this of your react-component. It is a object of a framework for example:

onFetchById(id) {
        var that = this;
        var url = '/user/' + id
        agent('GET', url).
            end().
            then(function onResult(res) {
                var result = JSON.parse(res.text);
                that.data = that.data.set('result', result);
                console.log(result);
                that.trigger(that.data);
            });
    },

Inside the then function my this isnt the react this. I bypass that problem by storing this in a variable called that at the beginning (var that = this;).

Upvotes: 5

Related Questions