-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Sharing: Implement Redux-based Publicize reducers and actions #338
Changes from all commits
76bc322
5f5c917
7d8b3fc
e461dc5
50586ea
8e28055
8bdd3d7
9c39f0e
1220fa3
c97533c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import React, { Component, PropTypes } from 'react'; | ||
import { connect } from 'react-redux'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import PostEditStore from 'lib/posts/post-edit-store'; | ||
import { fetchConnections } from 'lib/sharing/publicize/actions'; | ||
import { getConnectionsBySiteId, hasFetchedConnections } from 'lib/sharing/publicize/selectors'; | ||
import EditorSharingAccordion from './accordion'; | ||
|
||
class EditorSharingContainer extends Component { | ||
constructor( props ) { | ||
super( props ); | ||
|
||
// Set state | ||
this.state = this.getState(); | ||
|
||
// Trigger connection fetch | ||
this.ensureHasConnections(); | ||
|
||
// Bind legacy store update handler | ||
this.boundUpdateState = this.updateState.bind( this ); | ||
PostEditStore.on( 'change', this.boundUpdateState ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this needed? I'm guessing it has to do with the component not receiving There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Correct. In an ideal future scenario, we'd have the edited post contained within the global state tree, and we could pass it through to the component via the |
||
} | ||
|
||
componentDidUpdate() { | ||
this.ensureHasConnections(); | ||
} | ||
|
||
componentWillUnmount() { | ||
PostEditStore.off( 'change', this.boundUpdateState ); | ||
} | ||
|
||
ensureHasConnections() { | ||
if ( this.props.hasFetchedConnections ) { | ||
return; | ||
} | ||
|
||
this.fetchConnections(); | ||
} | ||
|
||
updateState() { | ||
this.setState( this.getState() ); | ||
} | ||
|
||
getState() { | ||
return { | ||
post: PostEditStore.get(), | ||
isNew: PostEditStore.isNew() | ||
}; | ||
} | ||
|
||
fetchConnections() { | ||
const { site, dispatch } = this.props; | ||
if ( ! site ) { | ||
return; | ||
} | ||
|
||
dispatch( fetchConnections( site.ID ) ); | ||
} | ||
|
||
render() { | ||
const { site, connections } = this.props; | ||
const { post, isNew } = this.state; | ||
|
||
return ( | ||
<EditorSharingAccordion | ||
site={ site } | ||
post={ post } | ||
isNew={ isNew } | ||
connections={ connections } | ||
fetchConnections={ this.fetchConnections.bind( this ) } | ||
className="editor-drawer__accordion" /> | ||
); | ||
} | ||
} | ||
|
||
EditorSharingContainer.propTypes = { | ||
site: PropTypes.object, | ||
dispatch: PropTypes.func.isRequired, | ||
hasFetchedConnections: PropTypes.bool, | ||
connections: PropTypes.array | ||
}; | ||
|
||
export default connect( | ||
( state, props ) => { | ||
return { | ||
hasFetchedConnections: props.site && hasFetchedConnections( state, props.site.ID ), | ||
connections: props.site ? getConnectionsBySiteId( state, props.site.ID ) : null | ||
}; | ||
} | ||
)( EditorSharingContainer ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the state mapping function always going to be the same? If not, why not (for my own education)? If so, it looks like this will be a common pattern going forward, so I think it makes sense to move this logic into a helper method like I'm also finding it pretty confusing that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This raises a good point, as it should depend on the data needs of the component. The
"State" is the terminology used by Redux, though I do agree that it becomes a bit confusing in this example where I'm injecting a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, now I remember why it wasn't simple to pass the subset of data -- since the selected site is not yet made available in the state tree, it's not possible to call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It appears that there is an alternate function signature for the |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,7 +69,10 @@ | |
"raf": "2.0.4", | ||
"react": "0.13.3", | ||
"react-day-picker": "1.1.0", | ||
"react-redux": "3.1.0", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm guessing you didn't go with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yep, |
||
"react-tap-event-plugin": "0.1.6", | ||
"redux": "3.0.4", | ||
"redux-thunk": "1.0.0", | ||
"rtlcss": "1.6.1", | ||
"sanitize-html": "1.11.1", | ||
"source-map": "0.1.39", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
`create-redux-store` | ||
==================== | ||
|
||
This module exports a function which, when invoked, returns an instance of a [Redux store](http://redux.js.org/docs/basics/Store.html). The store instance is intended to reflect the global state of the application, and runs dispatched actions against all reducers defined in [`reducers.js`](./reducers.js). To include a reducer in the global store, simply add the reducing function to the combined reducer exported by `reducers.js`. | ||
|
||
## Usage | ||
|
||
```js | ||
import createReduxStore from 'lib/create-redux-store'; | ||
|
||
const store = createReduxStore(); | ||
``` |
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 don't think
React
is needed here? I thinkimport { Component, PropTypes } from 'react';
would be sufficient.If I am wrong, can you explain so that I can learn?
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.
While React is not referenced directly in the file, it's still necessary to import. When transpiled, the JSX markup is replaced with calls to
React.createElement
, so React must be declared.The reason it is not marked as unused is because we use
eslint-plugin-react
in our ESLint configuration, which includes ajsx-uses-react
rule:https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md
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.
Cool, thanks for the explanation