-
Notifications
You must be signed in to change notification settings - Fork 289
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
Adding examples using context #80
Conversation
Removed the cryptic "end"-state and _dataVersion Changd _updateData() to refresh() to better represent the function's purpose
… adding a custom PropType that only checks for the presence of the setCallback function
Moved data into a prop and created a HOCed DataTable that is used in the actual example
TODO: FilterTable should probably be a HOC as well
Moved context to Ctxt....
Added a constant value 'fileName' without the EXAMPLES_LOCATION_BASE The file is autogenerated from the EXAMPLES_LOCATION_BASE
|
||
componentWillReceiveProps(nextProps) { | ||
if (JSON.stringify(nextProps.filters) !== JSON.stringify(this.state.filters)){ | ||
this.setState({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm converting props to state seems like an anti pattern and may cause 2 renders. Was there a reason you didn't just render off of this.props?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the prop is an object the values are passed as a reference and without the cloning I could not detect when the filter changed and when to update the parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My comment above was directed at calling set state rather than the JSON stringify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if I only do a comparison with the current filter prop it will already have changed since it's an object. That is why I need a cloned copy. Immutable would probably fix this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would happen if you deleted filters from state above and deleted componentWillReceiveProps and then called this.filter() as the first line in render?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This caused >1000 warnings:
warning.js:36 Warning: setState(...): Cannot update during an existing state transition (such as within
render
or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved tocomponentWillMount
.
Your solution would be more elegant but it doesn't seem to play well with React :-(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay cool. Next remove the setState calls here and remove this.state.filteredData from the render method and have it instead use an object returned from the this.filter method. Then I think you should be solid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent suggestion. I've removed all the setState for all the data-wrappers and moved them into the render method.
// This can be useful when you have more complex matches | ||
if (value instanceof Array) { | ||
const matches = value.map(x => match(x, filters[varName])).filter(x => x === true); | ||
// If all filters were identified then set this to true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems to work over all values not all filters. is the comment correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this was in case I have a single filter associated with an array of values - it's there just as an example how one could go about setting up a more complex filter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ya, just meant the comment is misleading / should be updated to reflect that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I changed to a for-loop I decided to remove this as well.
const row = this.state.rawData.getObjectAt(index); | ||
|
||
// Loop through all the filters and check if there's a match | ||
const found = Object.keys(filters) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't help but thing this could be written more cleanly with reduce or maybe use _.every
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of adding lo-dash but wasn't sure if adding more dependencies into the library was a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to add it for examples, but not the library. just make sure it's under devDependencies in npm and isn't used by any code under src
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The for loop solves this without adding it. I'll see if I'll need it later on.
return (!match(value, filters[varName])); | ||
}) | ||
.filter(x => x === true) | ||
.length === 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way this checks for no not matching filters here is a little weird to me.
Also you could gain performance if you don't run additional filters once a value fails a filter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this should probably be improved in some clever way. I've focused on getting it to work, a for loop with a break
should be smarter. I'm just used from R to avoid all for-loops and I'm not that familiar with the ups/downs of for-loops in JS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah with JS you should focus on readability. Often that's easier with functional approaches, but sometimes a loop is easier as well.
In R I think you get parallelism and other performance enhancements using a function because it drops down into compiled C to do the work. No advantages like that with JS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, changed to a for loop
} | ||
|
||
// Set the data filtering | ||
this.state.filteredData.setIndexMap(filteredIndexes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem very React-y / obeying one way data-flow to have the React lifecycle methods update the store which then updates React components...
I would recommend generating a list of filtered rows here and passing it into cells as a prop to render from (instead of the DataListWrapper). Alternatively we could do all of this in the DataListWrapper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, just me not being Reactified enough - changed to setState with a complete new DataListWrapper
.
I think passing the filter down to the cells moves logic that the filter cares about to elements that shouldn't have to be aware of that. The cells should only care about displaying the data, i.e. they need to be able to use whatever the getObjectAt
throws at them but filtering doesn't feel like anything that they should care about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed we should not pass down the filters, just a filtered data list
…d non-reacty wrapper behavior
Re-added pending-cell component
} | ||
} | ||
|
||
filter() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks better, thanks! I think we can go a bit further cleaning it up, but I'll wait until we have this using context since I think that will present it's own set of challenges and I don't want to get distracted.
Created an advanced example
Added comments and cleaned up code base
This message was created automatically by mail delivery software. A message that you sent could not be delivered to one or more of its dr.max.gordon@gmail.com ------- This is a copy of the message, including all the headers. ------ ----==_mimepart_582dc41d8367d_4b193fd87acc7134521d0 wcjordan commented on this pull request.
ya, just meant the comment is misleading / should be updated to reflect that You are receiving this because you authored the thread. @wcjordan commented on this pull request. In examples/CtxtFilterExample.js: > + if (Object.keys(filters).length > 0) { + const filteredIndexes = []; + for (let index = 0; index < this.state.rawData.getSize(); index += 1) { + const row = this.state.rawData.getObjectAt(index); + + // Loop through all the filters and check if there's a match + const found = Object.keys(filters) + .map((varName) => { + const value = row[varName]; + + // If we have a set of values e.g. an array + // If you're using immutablejs then you can just use List + // This can be useful when you have more complex matches + if (value instanceof Array) { + const matches = value.map(x => match(x, filters[varName])).filter(x => x === true); + // If all filters were identified then set this to true ya, just meant the comment is misleading / should be updated to reflect that — ----==_mimepart_582dc41d8367d_4b193fd87acc7134521d0-- |
Added except to clear propTypes from being propagated
…airbnb style guide
ContextExample touch ups
See issue #76. Here are examples of the filter and pagination table.
Description
fileName
that is concatenated with the EXAMPLES_LOCATION_BASE for generating thefile
elementMotivation and Context
Having a data as context allows creating manipulation of the data without knowing the
children
. This opens up for re-using filter-functionality while keeping a simple and nice JSX formatting such as:How Has This Been Tested?
Tested the examples in Chrome
Types of changes
Checklist: