Releases: glyph-cat/react-relink
Release list
4.3.2
4.3.1
- This package has been deprecated in favor of
cotton-box, which has a similar API design to React Relink. For information on migrating, please refer to the Migration Guide.
4.3.0
4.2.2
This release contains a bug fix for useRelinkValue where the state is returned as null if the active parameter is set to false in the beginning.
Consider the code below:
import { useState, useEffect } from 'react'
import { RelinkSource, useRelinkValue } from 'react-relink'
const SomeSource = new RelinkSource({
key: 'some-source',
default: 42,
})
function App(): JSX.Element {
const [active, setActive] = useState(false)
const someState = useRelinkValue(SomeSource, null, active)
useEffect(() => { setActive(true) }, [])
console.log(someState)
return <h1>Hello world</h1>
}Before fix:
| Render cycle | active |
someState |
Is expected value? |
|---|---|---|---|
| First | false |
null |
❌ No |
| Second | true |
42 |
✅ Yes |
After fix:
| Render cycle | active |
someState |
Is expected value? |
|---|---|---|---|
| First | false |
42 |
✅ Yes |
| Second | true |
42 |
✅ Yes |
4.2.1
4.2.0
- The default state of a source is now made accessible in hydration callbacks via the
defaultStateproperty
Source.hydrate(({ commit, defaultState }) => {
commit({ ...defaultState, ...fetchedState })
})- Fixed typing mistakes in some debugging messages
- Stability enhancements for edge cases that involve dynamic imports
4.1.0
Bug fixes
- Fixed issue where child dependencies with source keys of type
symbolwere not checked against when calling.cleanup()on the parent source, resulting in a false negative where no warnings are displayed.
API Changes
keyanddefaultare now exposed as read-only properties of theRelinkSourceclass. This way, it is no longer needed to go through the additional trouble of importing/exporting them when needed because they are already accessible through the source instance.- Deprecated
.cleanup()in favor of.dispose(). - By default,
.dispose()will wait for all queued actions to complete before actually disposing a source. There is aforceoption that can bypass that, but it is strictly intended for being used in teardown functions in tests only. - For hydration,
skipis deprecated and replaced bycommitDefault. There is also a new hydration strategy calledcommitNoopto complete the hydration without triggering any state changes. useRelinkValue(...)now accepts a third argument to control whether the hook should listen for state changes
// Without selector
useRelinkValue(Source, null, true /* or false */ )
// With selector
useRelinkValue(Source, selector, true /* or false */ )Miscellaneous
- Improved documentation in the TypeScript definition file as well as runtime messages for debugging (development env only) for more clarity.
- Compilation target of this package has been set to ES2020.
Known Issues
- In the examples of
.cleanup()and.dispose()in the.d.tsfile, creating sources in the render phase then disposing them in cleanup effects inStrictModewill cause an error. Indeed, eventually, the source is created and disposed twice, just as inteneded by Strict Mode, but the order in which they are created and disposed seems to be jumbled up.- Demonstration:
- Clone the repository, run
yarn install, then runyarn playground:web - Navigate to http://localhost:3000/dynamic-create-dispose
- During initial render, everything seems fine
- Click on "Increase counter", a TypeError will be thrown.
- Clone the repository, run
- Intended behaviour:
- 1st render phase: Source is created
- 1st Cleanup phase: Source is disposed
- 2nd render phase: Source is created
- Actual behaviour:
- 1st render phase: Source is created
- 2nd render phase: Source is created
- 1st Cleanup phase: Source is disposed
- Demonstration:
4.0.1
4.0.0
Support for Concurrent Rendering
This version adds compatibility for React 18's concurrent rendering by using the useSyncExternalStore hook.
Deprecated option: virtualBatch
Previously, Relink implements its own hook to subscribe to sources, watch for state changes, then decide if a component should update; but with useSyncExternalStore, Relink no longer has control over when to trigger component updates.
On the flipside, even though there is no 1:1 substitution, concurrent rendering might just be able to solve the problem virtualBatch has been trying to solve since day one — to make it possible to defer component updates for complicated states.
In fact, concurrent rendering provides a more granular control: in a sense that you can now tell React which "set state" calls are urgent and which ones are not, instead of only distinguishing them by sources.
Note: Basic selectors do not need to be memoized
// ✅ OK
function SomeComponent(): JSX.Element {
const someState = useRelinkValue(SomeSource, (state) => state.foo)
return /* ... */
}// ✅ Also OK
// Ideal for sharing with components in other files in a consistently manner.
export const someSelector = (state) => state.foo
function SomeComponent(): JSX.Element {
const someState = useRelinkValue(SomeSource, someSelector)
return /* ... */
}// ❌ Unnecessary
function SomeComponent(): JSX.Element {
const selector = useCallback((state) => state.foo, [])
const someState = useRelinkValue(SomeSource, selector)
return /* ... */
}Removal of deprecated APIs
These APIs are marked as deprecated in the previous version and is no longer included in this version.
- (deprecated -> new)
createSource->new RelinkSource(...)isRelinkSource->value instanceof RelinkSource
New exposed constants
(Probably rarely used)
BUILD_HASHBUILD_TYPERelinkBuildType