Skip to content

Commit fa58572

Browse files
timdorrmarkerikson
authored andcommitted
Use Hooks internally (aka 7.0) (#1209)
* 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)
1 parent eae14cc commit fa58572

25 files changed

+3595
-2352
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ test/react/*/test/**/*.spec.js
1212
test/react/**/src
1313
test/jest-config.json
1414
lcov.info
15+
.idea/
1516

1617
lib/core/metadata.js
1718
lib/core/MetadataBlog.js

.travis.yml

-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ language: node_js
22
node_js: node
33
cache: npm
44
env:
5-
- REACT=16.4
6-
- REACT=16.5
7-
- REACT=16.6
85
- REACT=16.8
96
script:
107
- npm test

docs/api/connect.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ The second parameter is normally referred to as `ownProps` by convention.
121121
122122
```js
123123
// binds on component re-rendering
124-
<button onClick={() => this.props.toggleTodo(this.props.todoId)} />
124+
;<button onClick={() => this.props.toggleTodo(this.props.todoId)} />
125125

126126
// binds on `props` change
127127
const mapDispatchToProps = (dispatch, ownProps) => {

docs/introduction/quick-start.md

-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ export default connect(
7575
)(Counter)
7676
```
7777

78-
7978
## Help and Discussion
8079

8180
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!

docs/using-react-redux/accessing-store.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,16 @@ export default connect(
4747
mapDispatch,
4848
null,
4949
{ context: MyContext }
50-
)(MyComponent);
50+
)(MyComponent)
5151

5252
// or, call connect as normal to start
5353
const ConnectedComponent = connect(
5454
mapState,
5555
mapDispatch
56-
)(MyComponent);
56+
)(MyComponent)
5757

5858
// Later, pass the custom context as a prop to the connected component
59-
<ConnectedComponent context={MyContext} />
59+
;<ConnectedComponent context={MyContext} />
6060
```
6161

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

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-redux",
3-
"version": "6.0.1",
3+
"version": "7.0.0-beta.1",
44
"description": "Official React bindings for Redux",
55
"keywords": [
66
"react",
@@ -36,7 +36,7 @@
3636
"coverage": "codecov"
3737
},
3838
"peerDependencies": {
39-
"react": "^16.4.0-0",
39+
"react": "^16.8.4",
4040
"redux": "^2.0.0 || ^3.0.0 || ^4.0.0-0"
4141
},
4242
"dependencies": {

rollup.config.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ const env = process.env.NODE_ENV
99

1010
const config = {
1111
input: 'src/index.js',
12-
external: Object.keys(pkg.peerDependencies || {}),
12+
external: Object.keys(pkg.peerDependencies || {}).concat('react-dom'),
1313
output: {
1414
format: 'umd',
1515
name: 'ReactRedux',
1616
globals: {
1717
react: 'React',
18-
redux: 'Redux'
18+
redux: 'Redux',
19+
'react-dom': 'ReactDOM'
1920
}
2021
},
2122
plugins: [
@@ -32,7 +33,8 @@ const config = {
3233
'node_modules/react-is/index.js': [
3334
'isValidElementType',
3435
'isContextConsumer'
35-
]
36+
],
37+
'node_modules/react-dom/index.js': ['unstable_batchedUpdates']
3638
}
3739
})
3840
]

src/alternate-renderers.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Provider from './components/Provider'
2+
import connectAdvanced from './components/connectAdvanced'
3+
import { ReactReduxContext } from './components/Context'
4+
import connect from './connect/connect'
5+
6+
import { getBatch } from './utils/batch'
7+
8+
// For other renderers besides ReactDOM and React Native, use the default noop batch function
9+
const batch = getBatch()
10+
11+
export { Provider, connectAdvanced, ReactReduxContext, connect, batch }

src/components/Provider.js

+23-31
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,55 @@
11
import React, { Component } from 'react'
22
import PropTypes from 'prop-types'
33
import { ReactReduxContext } from './Context'
4+
import Subscription from '../utils/Subscription'
45

56
class Provider extends Component {
67
constructor(props) {
78
super(props)
89

910
const { store } = props
1011

12+
this.notifySubscribers = this.notifySubscribers.bind(this)
13+
const subscription = new Subscription(store)
14+
subscription.onStateChange = this.notifySubscribers
15+
1116
this.state = {
12-
storeState: store.getState(),
13-
store
17+
store,
18+
subscription
1419
}
20+
21+
this.previousState = store.getState()
1522
}
1623

1724
componentDidMount() {
1825
this._isMounted = true
19-
this.subscribe()
26+
27+
this.state.subscription.trySubscribe()
28+
29+
if (this.previousState !== this.props.store.getState()) {
30+
this.state.subscription.notifyNestedSubs()
31+
}
2032
}
2133

2234
componentWillUnmount() {
2335
if (this.unsubscribe) this.unsubscribe()
2436

37+
this.state.subscription.tryUnsubscribe()
38+
2539
this._isMounted = false
2640
}
2741

2842
componentDidUpdate(prevProps) {
2943
if (this.props.store !== prevProps.store) {
30-
if (this.unsubscribe) this.unsubscribe()
31-
32-
this.subscribe()
44+
this.state.subscription.tryUnsubscribe()
45+
const subscription = new Subscription(this.props.store)
46+
subscription.onStateChange = this.notifySubscribers
47+
this.setState({ store: this.props.store, subscription })
3348
}
3449
}
3550

36-
subscribe() {
37-
const { store } = this.props
38-
39-
this.unsubscribe = store.subscribe(() => {
40-
const newStoreState = store.getState()
41-
42-
if (!this._isMounted) {
43-
return
44-
}
45-
46-
this.setState(providerState => {
47-
// If the value is the same, skip the unnecessary state update.
48-
if (providerState.storeState === newStoreState) {
49-
return null
50-
}
51-
52-
return { storeState: newStoreState }
53-
})
54-
})
55-
56-
// Actions might have been dispatched between render and mount - handle those
57-
const postMountStoreState = store.getState()
58-
if (postMountStoreState !== this.state.storeState) {
59-
this.setState({ storeState: postMountStoreState })
60-
}
51+
notifySubscribers() {
52+
this.state.subscription.notifyNestedSubs()
6153
}
6254

6355
render() {

0 commit comments

Comments
 (0)