Changelog
effector 20.8.2
combine
batching in a few edge cases with nested combine
callsimport {createEvent, createStore, combine} from 'effector'
const event = createEvent()
const $store = createStore(0).on(event, s => s + 1)
const $combined = combine([$store, combine([$store.map(d => d + 1)])])
$combined.watch(e => fn(e))
// => [0, [1]]
event()
// => [1, [2]]
Changelog
effector-react 20.8.0
Gate
state in createGate
via defaultState
fieldcreateGate({defaultState}) in documentation
object
restriction from createGate
Props
type in typescript, as it becomes useless with introduction of useGate
. This code now passes type checking successfullyimport {value createGate} from 'effector-react'
const RouteGate = createGate<string>()
const UserGate = createGate({defaultState: 'guest'})
Changelog
effector-react 20.7.3, effector-vue 20.4.2
effector-react/compat
and effector-vue/compat
compatibility with IE11Changelog
effector-react 20.7.1
useList
hook typings for typescript by allowing usage as components' return value (fix DefinitelyTyped issue)This code now works without type errors:
import {value createStore} from 'effector'
import {value useList} from 'effector-react'
const $users = createStore<User[]>([
{
username: 'alice',
email: 'alice@example.com',
bio: '. . .',
},
{
username: 'bob',
email: 'bob@example.com',
bio: '~/ - /~',
},
{
username: 'carol',
email: 'carol@example.com',
bio: '- - -',
},
])
const UserList = () => useList($users, ({username}) => <p>{username}</p>)
const App = () => (
<div>
<UserList />
</div>
)
Changelog
effector-react 20.7.0
useGate
, thereby making it consistent with <Gate />
createContextComponent
and createReactState
, which previously were based on createComponent
Changelog
effector 20.6.1, effector-react 20.4.1, effector-vue 20.3.2
Changelog
effector 20.9.0, effector-react 20.6.0
effector/fork
and effector-react/ssr
: api for server side rendering and managing independent instances of application in general./**
* app
*/
import {value createDomain, value forward, value restore} from 'effector'
import {
value useStore,
value useList,
value Provider,
value useEvent,
} from 'effector-react/ssr'
export const app = createDomain()
const requestUsernameFx = app.createEffect<{login: string}, string>()
const requestFriendsFx = app.createEffect<string, string[]>()
const $username = restore(requestUsernameFx, 'guest')
const $friends = restore(requestFriendsFx, [])
forward({
from: requestUserName.done.map(({result: username}) => username),
to: requestFriends,
})
const Friends = () => (
<ul>
{useList($friends, friend => (
<li>{name}</li>
))}
</ul>
)
const Title = () => <header>Hello {useStore($username)}</header>
export const View = ({root}) => (
<Provider value={root}>
<Title />
<Friends />
</Provider>
)
/**
* client
*/
import ReactDOM from 'react-dom'
import {value fork} from 'effector/fork'
import {value app, value View} from './app'
// initialize app with values from server
const clientScope = fork(app, {
values: window.__initialState__,
})
ReactDOM.hydrate(<View root={clientScope} />, document.getElementById('root'))
/**
* server
*/
import express from 'express'
import {value renderToString} from 'react-dom/server'
import {value fork, value serialize, value allSettled} from 'effector/fork'
import {value app, value View} from './app'
export const server = express()
server.get('/user/:login', async (req, res) => {
// clone application
const scope = fork(app)
// call requestUsername(req.params) in scope
// and await all triggered effects
await allSettled(requestUsername, {
scope,
params: req.params, // argument for requestUsername call
})
// save all stores in application to plain object
const data = serialize(scope)
// render dom content
const content = renderToString(<View root={scope} />)
res.send(`
<body>
${content}
<script>
window.__initialState__ = ${JSON.stringify(data)};
</script>
</body>
`)
})
This solution requires effector/babel-plugin
in babel configuration:
{
"plugins": ["effector/babel-plugin"]
}
Example application with express Serverless example
createApi
, stores created with restore
and events created with .prepend
to domain of given source unitsimport {createDomain, createApi, restore} from 'effector'
const domain = createDomain()
domain.onCreateStore(store => {
console.log('store created')
})
domain.onCreateEvent(event => {
console.log('event created')
})
const $position = domain.createStore({x: 0})
// => store created
const {move} = createApi($position, {
move: ({x}, payload) => ({x: x + payload}),
})
// => event created
const $lastMove = restore(move, 0)
// => store created