Skip to main content

Migration From react-relink

info

The usage of .get, .set, .reset, and .dispose remains the same.

Setup

Before
yarn add react-relink
Now
yarn add cotton-box cotton-box-react

Instantiation

Before
import { RelinkSource } from 'react-relink'

const ExampleSource = new RelinkSource({
key: 'example-source',
default: 'defaultState',
lifecycle: {
init({ commit, commitNoop, defaultState }) {
// ...
},
didSet({ state }) {
// ...
},
didReset() {
// ...
},
},
options: {
suspense: true | false,
public: true | false,
},
scope: OtherSource,
})
Now
import { AsyncStateManager, StateManagerVisibility } from 'cotton-box'

// Default state is passed as first parameter,
// remaining options are passed as the second.
const ExampleState = new AsyncStateManager('defaultState', {
// `key` is no longer needed, but there is a `name` property,
// which is *optional* and only used for debugging.
lifecycle: {
init({ commit, commitNoop, defaultState }) {
// ...
},
// `defaultState` is exposed here:
didSet({ state, defaultState }) {
// ...
},
didReset() {
// ...
},
},
// New option:
clientOnly: true | false,
// `visibility` is a boolean type in react-relink:
visibility: StateManagerVisibility.ENVIRONMENT,
suspense: true | false,
// Scope is not supported by Cotton Box
})

Consuming the State

Before
function App() {
import { useRelinkValue } from 'react-relink'

const state = useRelinkValue(ExampleSource)
return '...'
}
Now
function App() {
import { useStateValue } from 'cotton-box-react'

const state = useStateValue(ExampleState)
return '...'
}

Handling dependencies

Before
const ExampleSourceA = new RelinkSource({
key: 'example-source-a',
default: '...',
lifecycle: { /* ... */ },
})

const ExampleSourceB = new RelinkSource({
key: 'example-source-b',
default: '...',
deps: [ExampleSourceA],
lifecycle: { /* ... */ },
})
Now
const ExampleStateA = new StateManager('...')

const ExampleStateB = new StateManager('...', {
lifecycle: {
init() {
await ExampleStateA.isInitializing.wait(false)
// continue to do something
},
},
})

Re-initialization

Before
MySource.hydrate(...)
Now
ExampleState.init(...)

Scope

Cotton Box does not have Scope-related APIs to reduce complexity. Instead, we recommend using React's Context API as a substitute as it allows more fine-grained control at the same time.