Skip to content

Commit

Permalink
Use Hooks internally (aka 7.0) (#1209)
Browse files Browse the repository at this point in the history
* Update React to latest

* Update React peer dependency to 16.8.x

* Initial re-implementation of `connectAdvanced` using hooks

Matches changes from v7.0.0-alpha.1

* Update tests to match v7-alpha.1 behavior

Added rtl.act() calls around dispatches and other component updates
Added clarification on expected mapState calls in some places
Disabled some no-longer-relevant tests per implementation
Made tests run against React 16.8 by default

* adding a react hooks test that fails with v7 alpha

* wrapping store.dispatch with rlt.act, fixes component renders

* reducing hooks test to 2 components

* Fix case where wrapper props changed before store update render

* Mark ReactDOM as global in UMD builds

Matches state as of v7.0.0-alpha.2

* Fix perf problems with out-of-bounds array access

Matches state as of v7.0.0-alpha.3

* Add modules to handle importing batchedUpdates

* Use appropriate batched update API for subscriptions

* Inject unstable_batchedUpdates in default entry point

* Provide an alternate entry point for alternate renderers

Matches state as of v7.0.0-alpha.4

* Remove batch arg from createListenerCollection (#1205)

This prevents a bug with Terser (webpack's default minifier) where the
returned batch function isn't defined due to function inlining.

Matches state as of v7.0.0-alpha.5

* Remove older React versions from Travis

* Add comments to connectAdvanced. Many much comments!

* Re-add test for a custom store as a prop

* Fix null pointer exception when store is given as a prop

We were trying to read contextValue.subscription, even if that
value was null.  Reworked logic to handle cases where the store
came in as a prop.

* Ensure wrapper props are passed correctly when forwarding refs

* Add a test to verify subscription passthrough with store-as-prop

* add non-batched tests (#1208)

* Force SSR tests to mimic a Node environment

* Restructure connect tests to group by category for easier reading

Yeah, this kills the blame history. Sorry. But it's a lot easier
to figure out what the tests are used for now.

* Clean up dead code in Provider tests

* Add tests to verify errors are thrown for bad mapState functions

* Fix edge cases around saved wrapper props and error handling

Changed to useLayoutEffect to ensure that the lastWrapperProps ref
is written to synchronously when a render is committed. However,
because React warns about this in SSR, added a check to fall back
to plain useEffect under Node so we don't print warnings.

Also added logic to ensure that if an error is thrown during a
mapState function, but the component is unmounted before it can
render, that the error will still be thrown.  This shouldn't happen
given our top-down subscriptions, but this will help surface the
problem in our tests if we ever break the top-down behavior.

* Formatting

* Add a test to verify no errors are printed in SSR usage

* Ignore .idea/

* 7.0.0-beta.0

* Updated outdated SSR-test (dispatch in ancestors) (#1213)

* Added test for injecting dynamic reducers on client and server (#1211)

* Remove WebStorm gitignore

This goes in a global gitignore file, not a project.

* [FIX]: #1219 Save references before update (#1220)

* Re-ignore .idea/

* 7.0.0-beta.1

* Update the codecov config to be more forgiving.

* add test to verify that mapStateToProps is always called with latest store state (#1215)
  • Loading branch information
timdorr authored and markerikson committed Apr 9, 2019
1 parent eae14cc commit fa58572
Show file tree
Hide file tree
Showing 25 changed files with 3,595 additions and 2,352 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ test/react/*/test/**/*.spec.js
test/react/**/src
test/jest-config.json
lcov.info
.idea/

lib/core/metadata.js
lib/core/MetadataBlog.js
Expand Down
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ language: node_js
node_js: node
cache: npm
env:
- REACT=16.4
- REACT=16.5
- REACT=16.6
- REACT=16.8
script:
- npm test
Expand Down
2 changes: 1 addition & 1 deletion docs/api/connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ The second parameter is normally referred to as `ownProps` by convention.
```js
// binds on component re-rendering
<button onClick={() => this.props.toggleTodo(this.props.todoId)} />
;<button onClick={() => this.props.toggleTodo(this.props.todoId)} />

// binds on `props` change
const mapDispatchToProps = (dispatch, ownProps) => {
Expand Down
1 change: 0 additions & 1 deletion docs/introduction/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export default connect(
)(Counter)
```


## Help and Discussion

The **[#redux channel](https://discord.gg/0ZcbPKXt5bZ6au5t)** of the **[Reactiflux Discord community](http://www.reactiflux.com)** is our official resource for all questions related to learning and using Redux. Reactiflux is a great place to hang out, ask questions, and learn - come join us!
Expand Down
8 changes: 4 additions & 4 deletions docs/using-react-redux/accessing-store.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ export default connect(
mapDispatch,
null,
{ context: MyContext }
)(MyComponent);
)(MyComponent)

// or, call connect as normal to start
const ConnectedComponent = connect(
mapState,
mapDispatch
)(MyComponent);
)(MyComponent)

// Later, pass the custom context as a prop to the connected component
<ConnectedComponent context={MyContext} />
;<ConnectedComponent context={MyContext} />
```

The following runtime error occurs when React Redux does not find a store in the context it is looking. For example:
Expand Down Expand Up @@ -132,7 +132,7 @@ function MyConnectedComponent() {
// component where it can be used in lifecycle methods
}}
</ReactReduxContext.Consumer>
);
)
}
```

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-redux",
"version": "6.0.1",
"version": "7.0.0-beta.1",
"description": "Official React bindings for Redux",
"keywords": [
"react",
Expand Down Expand Up @@ -36,7 +36,7 @@
"coverage": "codecov"
},
"peerDependencies": {
"react": "^16.4.0-0",
"react": "^16.8.4",
"redux": "^2.0.0 || ^3.0.0 || ^4.0.0-0"
},
"dependencies": {
Expand Down
8 changes: 5 additions & 3 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ const env = process.env.NODE_ENV

const config = {
input: 'src/index.js',
external: Object.keys(pkg.peerDependencies || {}),
external: Object.keys(pkg.peerDependencies || {}).concat('react-dom'),
output: {
format: 'umd',
name: 'ReactRedux',
globals: {
react: 'React',
redux: 'Redux'
redux: 'Redux',
'react-dom': 'ReactDOM'
}
},
plugins: [
Expand All @@ -32,7 +33,8 @@ const config = {
'node_modules/react-is/index.js': [
'isValidElementType',
'isContextConsumer'
]
],
'node_modules/react-dom/index.js': ['unstable_batchedUpdates']
}
})
]
Expand Down
11 changes: 11 additions & 0 deletions src/alternate-renderers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Provider from './components/Provider'
import connectAdvanced from './components/connectAdvanced'
import { ReactReduxContext } from './components/Context'
import connect from './connect/connect'

import { getBatch } from './utils/batch'

// For other renderers besides ReactDOM and React Native, use the default noop batch function
const batch = getBatch()

export { Provider, connectAdvanced, ReactReduxContext, connect, batch }
54 changes: 23 additions & 31 deletions src/components/Provider.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,55 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { ReactReduxContext } from './Context'
import Subscription from '../utils/Subscription'

class Provider extends Component {
constructor(props) {
super(props)

const { store } = props

this.notifySubscribers = this.notifySubscribers.bind(this)
const subscription = new Subscription(store)
subscription.onStateChange = this.notifySubscribers

this.state = {
storeState: store.getState(),
store
store,
subscription
}

this.previousState = store.getState()
}

componentDidMount() {
this._isMounted = true
this.subscribe()

this.state.subscription.trySubscribe()

if (this.previousState !== this.props.store.getState()) {
this.state.subscription.notifyNestedSubs()
}
}

componentWillUnmount() {
if (this.unsubscribe) this.unsubscribe()

this.state.subscription.tryUnsubscribe()

this._isMounted = false
}

componentDidUpdate(prevProps) {
if (this.props.store !== prevProps.store) {
if (this.unsubscribe) this.unsubscribe()

this.subscribe()
this.state.subscription.tryUnsubscribe()
const subscription = new Subscription(this.props.store)
subscription.onStateChange = this.notifySubscribers
this.setState({ store: this.props.store, subscription })
}
}

subscribe() {
const { store } = this.props

this.unsubscribe = store.subscribe(() => {
const newStoreState = store.getState()

if (!this._isMounted) {
return
}

this.setState(providerState => {
// If the value is the same, skip the unnecessary state update.
if (providerState.storeState === newStoreState) {
return null
}

return { storeState: newStoreState }
})
})

// Actions might have been dispatched between render and mount - handle those
const postMountStoreState = store.getState()
if (postMountStoreState !== this.state.storeState) {
this.setState({ storeState: postMountStoreState })
}
notifySubscribers() {
this.state.subscription.notifyNestedSubs()
}

render() {
Expand Down
Loading

0 comments on commit fa58572

Please sign in to comment.