-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
this.state does't work at listView's renderRow #1133
Comments
you're calling setState twice. doesn't this cause it to render twice as well? maybe a race is happening?
|
|
There's no problem in calling The issue there is that https://facebook.github.io/react/docs/component-api.html#setstate |
I know the |
|
Oh, I see, I had a look on the source, but I'm not sure what's the best solution here. /cc @vjeux |
Try always returning true from rowHasChanged. Better solution is not to access this.state/this.props/this.context/any non-constant instance variable or global variable from renderRow, and instead pass data through only the data source. The docs should probably mention this as a rule of thumb since there have been a couple similar issues opened. |
I tried the |
I've tried to do the same thing as well some days ago and had no real luck. Some things a tried (which are kind of dirty though):
I'm currently living with the last option, although it has probably some disadvantages. Had no time to investigate it any further. |
Good point, you need to force a data source update too. Option 3 of cloning a data source with the same content should provide the desired behavior. For the API it would be easier if hasRowChanged were replaced with shouldComponentUpdate plus component pooling to avoid allocations. I haven't thought through the details but I think we want a React-style API instead of this UIKit-inspired one. |
Although I remember that option 3 (creating a new DS) did not work as well in some scenarios as the rows were not re-rendered (debugged a little bit into it and noticed that even with a new DS, the re-render method was not executed). Thats why I finally began to use option 4. I remember discussing with someone about that topic over there @ freenode about 2 or 3 days ago, but can't remember anymore. My context was adding a new item in a gridview (https://github.com/lucholaf/react-native-grid-view) on the same row, which did not make RN to re-render the row. |
I've also been having problems with this. For me, I was trying to render a list of notifications, each with a time associated. So, like like how tweets are labeled "2m ago". I initially tried calculating the relative times inside renderRow, but that didn't work. So, I ended up cloning notifications (via JSON.parse(JSON.stringify(notification)). That worked, but would spuriously cause some of my rows to become blank whenever the row changed enough (going from "4s ago" to "5s ago" was fine, but going from "9s ago" to "10s ago" wasn't). So, I then tried removing the time from my renderRow function, so it'd just render the notification. The time was still being updated in the background, it just wasn't being displayed. This, indeed, would make my rows more stable, and they no longer disappear randomly. After reading @ide's suggestion above, then set put all my times into state, but still caused my rows to spuriously become blank. Once again, removing the times fixed the issue. I'm still not sure why this is. Have you encountered these problems, @PhilippKrone? Edit: nevermind the blank text problem. @ide graciously debugged with me over IRC, and it was mentioned / fixed in #813. Thanks again, @ide! |
clone the origin DS to force the renderRow render again works. Thanks a lot. var _ds = JSON.parse(JSON.stringify(ds));
that.setState({
dataSource: that.state.dataSource.cloneWithRows(_ds),
updatePressed: true
}); |
@iahu could you share more details on this code? What is the context? |
@kevinzzz007 source code is here https://gist.github.com/iahu/0e524f4612a8925f2f9c |
@iahu How did you manage to force the ListView to re-render? I didn't see anywhere you created |
OK, I have update my gist. |
@iahu thanks! That made it really clear. So in my case, I got my data from ParseReact, here is my code:
|
You need to make a clone of you original datasource. That means it's must be a "immutable object".
|
@iahu yeah, I tried that, an issue with that is my Parse object has date object in it, which if I run the object through |
@kevinzzz007 try this code var d = this.data.driver_available_times;
var _ds = new Date(d); // d !== _ds, make a clone of your Date object. |
@iahu thanks! I will give it a shot :-) |
re-create the datasource by changing a dummy value (so that the rows are re-rendered). |
|
@fiowind that makes sense, I might try this solution in the future, but I do think there should be an option for us to reload the |
ListView is designed to have all data for renderRow come from the data source. I recommend putting the selection state in the row data of the data source and updating that with clone and setState. Does that work? Sounds like some documentation improvements would help... |
this.state.todoItemArray = this.state.todoItemArray.concat({ 'Item': item, 'TodoItemstyle': todoItembgStyle }); Use Concat.. it will work.. adding new list item to the datasource... Here TodoItemArray is my datasource.. |
I update the this.state.pressTest on my
onItemPress
method (gist), and hope can get the newly state of pressTest (gist).But, it does't work on my code.why? thx.
The text was updated successfully, but these errors were encountered: