keajs / kea Goto Github PK
View Code? Open in Web Editor NEWBatteries Included State Management for React
Home Page: https://keajs.org/
License: MIT License
Batteries Included State Management for React
Home Page: https://keajs.org/
License: MIT License
Currently I'm using ReactQL for my go-to starter as it offers a seemless development environment for React/Redux/Apollo/Webpack stack
from their documentation:
ReactQL is React + GraphQL done properly — for Mac, Windows and Linux.
It combines best-of-breed choices for UI, GraphQL data fetching, CSS and code bundling, > handles server-side rendering (SSR) properly, and is fast and extensible. You can choose Javascript or Typescript flavours.
It focuses on performance characteristics that you don't often find in other starter kits — offering Zopfli/Brotli compression, automatic vendor splitting, aggressive minification of JS/CSS, instant hot code reloading and more, out-the-box.
It pairs an async web server for handling SSR, non-JS imports (like images, CSS, etc) and works universally. Your code will run both in the browser, and on the server — even inline imports!
Development, production and even static bundling can be invoked with just one command, via the ReactQL CLI.
You can easily bolt-on your own GraphQL server, or point to one off-site.
If you want to shave weeks off your next project boilerplate, try ReactQL.
If you could help me to get it working, i'll try to submit a PR on reactql kit repository and convince the ReactQL author to get it officially supported.
The kea starter kit is good, but I believe if we could get more boilerplate to use Kea, it will bring more attention to the community and more people will start using the library.
This is what I have so far:
wmhafiz/reactql-kea#1
It seems to be working, except there's an error in the console log
[KEA-LOGIC] Path starting with "scenes" is not connected to the reducer tree! (3) ["scenes","counter", "index"]
Any idea where did i do wrong?
Thanks!
I'm looking at using redux-pouchdb-plus for persistence. The integration requires wrapping persistentReducer around reducers to be saved to the db. Looking for suggestions on how to do that with reducers generated by Kea.
Currently commander
is listed as a dependency. Would it make more sense to move this and other CLI related libs into a separate repo kea-cli
so these do not get bundled with production builds?
Also, is there a reason why this library is including a specific hash?
tj/commander.js#c6236d9504b60d9a2e6aa7fc3ce17a12f48f4a3e
It is giving me issues when trying to add it with yarn behind a corporate proxy.
Thanks!
Creating a new application according documentation "Starting a new kea app from scratch" with Windows 10 gives an error about rm-command which obviously is not available from Windows command prompt.
Given command and error are as follows:
C:\temp\foobar>kea new my-project
Creating new project "my-project" with template "default" (keajs/kea-example)
--> Running: git clone --quiet --depth=1 --branch=master https://github.com/keajs/kea-example ./my-project && rm -rf ./my-project/.git
'rm' is not recognized as an internal or external command,
operable program or batch file.
child_process.js:524
throw err;
^
Error: Command failed: git clone --quiet --depth=1 --branch=master https://github.com/keajs/kea-example ./my-project && rm -rf ./my-project/.git
'rm' is not recognized as an internal or external command,
operable program or batch file.
at checkExecSyncError (child_process.js:481:13)
at execSync (child_process.js:521:13)
at Object.<anonymous> (C:\Users\foo\AppData\Roaming\npm\node_modules\kea\lib\cli\kea-new.js:50:1)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:427:7)
Two questions,
this.props
Eg,
// if task reducer had following properties
{
data: [],
loading: false
}
@connect({
actions: [
session, ['storeSession'],
tasks, ['*']
],
props: [
session, ['isLoggedIn'],
tasks, ['*']
]
})
//somewhere in component, I should be able to use like this:
this.props.tasks.data;
this.props.tasks.loading
this.props.session.isLoggedIn
this.actions.session.login();
this.actions.tasks.load();
Right now:
const logic = kea({
workers: {
* doSomething () {
// ...
}
}
})
console.log(logic.workers) // undefined
In order to test your workers, you should be able to access them.
When setting the path option to:
path: () => ['root']
Then the following error occurs:
index.js:92 [KEA-LOGIC] Can not add reducer to "root". There is something in the way: {}
I'm trying to create a selector that takes an id that is passed to the component through props and uses that id to pull the object out of a kea reducer that has that id. This is a case where i want to use a selector but I can't figure out how to make the selector get recalculated whenever the prop changes.
Here's an example to demonstrate what i'm trying to accomplish. There is a books
reducer that has a dictionary of books based on their id.
books = {
0: { title: "My Book" },
1: { title: "My Other Book" },
}
Now I have a component that gets passed a book id:
<BookDetail bookId={0} />
<BookDetail bookId={1} />
I want to intercept the bookId
that was passed to BookDetail and inject a book
prop. However, the selector i have defined doesn't get called for each BookDetail component. It only gets called once because the input selector hasn't changed. The only input selector is the books
reducer, which hasn't changed in this case. Is there a way to tell kea to reevaluate a selector when a prop changes?
@kea({
reducers: ({ actions }) => ({
books: [null, PropTypes.object, {}],
}),
selectors: ({ selectors, props }) => ({
book: [
() => [selectors.books],
books => books[props.bookId],
PropTypes.object,
],
}),
});
Any help you can give would be appreciated. I've liked kea so far but it feels like what i'm trying to do shouldn't be difficult because it's so easy to do with reselect.
Awesome work! Is this library react native friendly?
Looking at the code for getState I noticed initial state can not be passed, this forces me to rely on the manual method for setting up my store, is there a specific philosophy behind this?
I need it for both mocking the store in react-cosmos as well as server side rendering.
Would be great to see how to connect Kea scenes with an existing redux applications.
Unrelated - any preferred ways to extend kea logic in a uniform way without creating an instance first? Something like there is a "logic creator" function in a "Form" tutorial in the docs, but with a way to override / add to everything? I realize it can become cumbersome with the way we define connections in kea (array > array > syntax-reach string).
Extend === override actions / reducers / sagas / workers / connect
Hi there!
I'm using Kea at work with Relay Modern and I noticed that Kea has a dependency on Redux Saga. I think it would be better to have the Redux Saga support as a separate package in case that a user has a different async library.
Any thought on adding redux-observable support?
Could look something like:
@kea({
key: (props) => props.id,
path: (key) => ['scenes', 'homepage', 'slider', key],
actions: () => ({
updateSlide: index => ({ index })
}),
reducers: ({ actions, key, props }) => ({
currentSlide: [props.initialSlide || 0, PropTypes.number, {
[actions.updateSlide]: (state, payload) => payload.key === key ? payload.index % images.length : state
}]
}),
selectors: ({ selectors }) => ({
currentImage: [
() => [selectors.currentSlide],
(currentSlide) => images[currentSlide],
PropTypes.object
]
}),
epic: (action$, store, selectors) => action$
.ofType(SOMETHING_INIT)
.map(() =>
selectors.getSlideImages(store.getState())
)
.map(images => ({
...images,
...getSlideMetaData(store.getState(), images.cardSelection)
}))
//..etc...
})
Ok, here is the case. And please correct me if I'm trying to achieve this the "wrong way".
I have an auth
logic which looks something like this:
// logic/auth.js
export default koa({
// ... actions, path, etc.
reducers: ({ actions }) => ({
user: [null, PropTypes.object, {
[actions.setUser]: (_, user) => user,
}],
}),
});
Then I want to have a HOC
which is called CheckPermissions
and it should, given the permissionsCheckCallback
, render children only if the provided function returns true
.
Now, the way I would go about it with vanilla redux is to have the CheckPermissions
component connected with the store by giving it a mapStateToProps
function which would:
user
from the provided state
permissionsCheckCallback
function from ownProps
{ hasPermissions: permissionsCheckCallback(user) }
This way component is never rerendered even if the user changes but the permissions stay the same (optimal).
Now, I've started doing this in kea
by having the CheckPermissions
component (pure function really...) export this:
// components/CheckPermissions.jsx
import Auth from '../logic/auth';
import { connect } from 'kea';
export default connect({
props: [
Auth, [
'user',
],
],
})((props) => (
props.hasPermissions(props.user)
? props.children
: null
))
But, the mapStateToProps
concept is happening inside the component, not outside so it does not stop the "rerender" cycle: if the user changes - even if the permissions do not - it will trigger the render.
Now, either I'm not reading the docs right / not getting some core concept of kea
or this is not possible to do the kea
way? Sure, I can always target the user
from the global state (no need to even connect Auth
) but this is why I'm trying to use kea
, so I don't have to think about the "global" state and bring "logic" as needed (again - this may be wrong on many levels, and kea
is not intended to be used this way).
I just stumbled across this project. I really like what you're doing here, but I find myself wondering if I could integrate kea into my already existing react/redux/saga project. I expect I would have many components that would need access to kea-based infrastructure as well as the manually wired stuff I already have. Is there an elegant way to combine these two? I suppose I could wrap my kea-generated stuff with connect()
from react-redux, but it would be nice to have a cleaner option.
If you have any suggestions, you might want to add it to the documentation.
I didn't know where to best place this but I'd like to know if there are any plans to create this as an HOC for functional components and just passing all the state and actions down as props?
Thanks!
Looks like this library changed recently to use a new getStore
method that wraps of a lot of the redux stuff together.
Is there a way to provide the compose function to getStore
so that I can use the composeWithDevTools
from remote-redux-devtools?
Looks like there is a fallback shown at the bottom of the getStore
documentation, but using the new getStore
abstraction would be nice.
"kea": "^0.25.1",
Hey, just curious to know and to start collecting data for a future "projects" page: who's using Kea in the real world? :)
Please share:
Hello there,
so, after quite a bit of debugging I noticed that including plugins directly works
// components/Users.js
...
import thunkPlugin from "kea-thunk";
import { kea } from "kea";
export default kea({
plugins: [thunkPlugin],
path: () => ["kea", "Users"],
thunks: ({ actions }) => {
...
})(function Users(props)=>{...})
however registering plugins on the store level does not
// store.js
import thunkPlugin from 'kea-thunk'
import { getStore } from "kea";
export const createStore = preloadedState => getStore({ plugins: [thunkPlugin] })
upon inspection I noticed that the kea
function is executed before the ActivatePlugins function is.
This happens even if I call the store before importing the component for some reason 🤔
// pages/index.js
import React, {Component} from 'react'
import { Provider } from 'react-redux'
import { createStore } from '../store'
let store = createStore()
import Users from '../components/Users'
export default class LandingPage extends Component {
render() {
return <Provider store={store}>
<Users/>
</Provider>
}
}
And once the logic is initialized the global plugin is never referred to later
in this case all actions declared in thunks
never show up.
so far I resolved this by simply directly including the plugin
any idea why?
my current proposed solutions are make global plugins run on already initialized logic
allways use plugins on the logic level (which I will do until a solution is presented)
in the mean time
I only figured out I can use plugins on the logic level by following by inspecting the code
would be nice if this is mentioned in the thunk plugin documentation
I realized later it's already mentioned in the kea function documentation but it's kinda not where I would have looked when faced with a problem related to a plugin
thank you for you time 😃
Hey, currently there is only one example in the guide: TodoMVC
We need some more examples to showcase the functionality of kea
, much like SoundRedux did for Redux.
Currently I can point to my own startup, a freelance project (and a few others) or to an alpha-stage open source data analytics platform when anyone asks for examples of projects that use kea in production. The last of the three has the source available, but is using an older version of kea.
Thus it would be great to have some fresh examples.
Is anyone up for the challenge of writing some?
Some ideas:
Other ideas?
I may be doing something wrong but I can't make the PropTypes validation works. If I have something like this:
import React from 'react'
import PropTypes from 'prop-types'
import { kea } from 'kea'
const counterLogic = kea({
actions: () => ({
increment: amount => ({ amount }),
decrement: amount => ({ amount })
}),
reducers: ({ actions }) => ({
counter: [0, PropTypes.number, {
[actions.increment]: (state, payload) => state + payload.amount,
[actions.decrement]: (state, payload) => state - payload.amount
}]
})
})
const Counter = ({
actions: {
increment, decrement
},
counter
}) =>
<div>
<div>{ counter }</div>
<button onClick={() => increment(1)}>+</button>
<button onClick={() => decrement(1)}>-</button>
</div>
export default counterLogic(Counter)
It works fine. But if I change the increment
calling to something like this:
<button onClick={() => increment('abc')}>+</button>
It should raise an exception, right? Like it does with component proptypes validation.
But I'm not getting anything from console. If you run this component and try to increment
something different from a number (like a 'abc'
string), your component will receive '0abc'
from counter
prop. Maybe I'm doing something wrong or maybe it's a bug. I don't know, lol
kea
has been under development for more than a year by now. It started out with a completely different syntax to the recommended kea({})
approach, which is now well documented. The old ways are still available, but I want to remove them.
For example, what is now achieved with kea({})
was before achieved through Logic
classes like so: https://gist.github.com/mariusandra/1b8eeb3f2f4e542188b915e27133c858
For sagas we had/have separate Saga classes that looked like this: https://gist.github.com/mariusandra/e6091b393e153c9edf3ba451a9d91aeb
There are also the old createLogic
, createSaga
, createKeaStore
functions which are still exported and take up valuable bundle size.
In addition to all of that, I once implemented a way to have namespaced props, like so: keajs/kea-website@dcf107e
This is still usable for the old connect method (imported from kea/logic
), but not anymore in the newer kea({})
syntax or the new connect
alias. This approach was fun, but it screwed over propTypes and made the entire codebase more complex. I don't think anyone ever used them? To delete and simplify?
None of the above is tested.
All of this baggage is still there in kea v0.19
. Should we hold on to this deprecated functionality going forward? What is the cost of removing them?
I'm writing this issue to address these points:
@meikoudras @madisvain - as the two confirmed pre-0.19 kea users, do you have any opinion on these points?
My idea is to plant strong "deprecated" warnings for all of this in v0.20 and remove them by v0.22. I could keep the Saga
classes around a bit longer, as the code for them is ridiculously simple
Kea provides a very concise way of collecting application logic, making it a really tempting framework to operate on, but why are its plugins so large?
In the previous image I included all packages even though I intend to only include thunk
but even still how can a mere wrapper have the same size as kea itself.
it makes some sense for kea being 21kb gzipped ; however the numbers I'm seeing suggests that kea could be suffering from maybe bad bundling, or at least the async plugins.
just wondering
Hi, I love how kea abstract things. But is it supporting redux-thunk or not? Do you have sort of road map for supporting X in the future?
Hi, I'm using create-react-app
for my project and I followed the instructions listed in the documentation located here:
https://kea.js.org/guide/installation
The instructions I followed was Adding to apps made with create-redux-app.
After running through all of the following I npm start
my application and I'm receiving the following errors.
ReferenceError: regeneratorRuntime is not defined
I figured this might just be an issue with the node_modules
so I removed the entire node_modules folder and went ahead and re-installed all the packages using npm install
since everything I installed the previous time had the --save
flag, so essentially that would give me a clean copy of all my dependencies. Still receiving the same error.
Am I missing something??
This is what my package.json
looks like:
{
"name": "app",
"version": "0.1.0",
"private": true,
"dependencies": {
"bulma": "^0.5.1",
"custom-react-scripts": "^0.1.4",
"flow-bin": "^0.52.0",
"font-awesome": "^4.7.0",
"history": "^4.6.3",
"husky": "^0.14.3",
"kea": "^0.20.8",
"lint-staged": "^4.0.2",
"node-sass-chokidar": "0.0.3",
"npm-run-all": "^4.0.2",
"prettier": "^1.5.3",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-redux": "^5.0.6",
"react-router-dom": "^4.1.2",
"react-router-redux": "^4.0.8",
"redux": "^3.7.2",
"redux-saga": "^0.15.6",
"reselect": "^3.0.1"
},
"lint-staged": {
"src/**/*.{js,jsx,json,css}": [
"prettier --single-quote --write",
"git add"
]
},
"scripts": {
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build": "npm run build-css && react-scripts build",
"flow": "flow",
"precommit": "lint-staged",
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"devDependencies": {
"@storybook/react": "^3.2.3"
}
}
At the moment I'm trying out Kea in a new project but I'm still confused about a couple of things. Maybe it is because I'm not that well-versed in Redux/Redux saga. I've got an application where I simply want to send some data json I fetched as a property. The action is called setCurrentArticle
.
I've placed the actual fetch call in a worker function called fetchArticleData
. Now it does fetch the data, but it keeps on looping after that. Am I missing something fundamental here?
takeLatest: ({ actions, workers }) => ({
[actions.setCurrentArticle]: workers.fetchArticleData,
}),
workers: {
* fetchArticleData(action) {
const { setCurrentArticle } = this.actions;
const id = action.payload.currentArticle.id;
const url = `${apiEndpoints.root}stories-api/${id}`;
const response = yield call(fetch, url);
if (response.status === 200) {
const json = yield response.json();
yield put(setCurrentArticle(json));
}
},
},
Why I have regeneratorRuntime is not defined
error? I've installed regenerator-runtime and still nothing changes.
Note: I use create-react-app
If initFromProps
is undefined here, nothing happens:
threads: [[], PropTypes.array, {
[initFromProps]: (_, payload) => payload.threads,
}]
Hi
Whats the proper setup to unit test the reducers and selectors defined in kea? do we use connect to import them in our tests?
Thanks!
I found this while trying out kea in an existing app. I have a HOC that uses connect
from react-redux. Long story short, you can't call kea({...options})(MyComponent)
if MyComponent
has already had connect
(from react-redux) called on it.
If you do this and call the actions defined in your kea options, the actions will fire but the corresponding sagas will not run.
More (too much?) detail:
export default function HOC(callback, mapStateToProps, mapDispatchToProps) {
return function factory(WrappedComponent) {
class Wrapper extends PureComponent {
componentDidMount() {
callback(this.props);
}
render() {
return <WrappedComponent {...this.props} />
}
}
return connect(mapStateToProps, mapDispatchToProps)(Wrapper);
}
}
// in another file...
const Logic = kea({
actions: () => ({
greet: person => ({person}),
}),
workers: {
handleGreeting: function* (action) {
yield call(hello, action.payload.person);
// etc...
},
},
takeEvery: ({actions, workers}) => ({
[actions.greet]: workers.handleGreeting,
}),
});
const SillyComponent = props => (<div>Sent a greeting to {props.person}</div>);
// dispatch api call on mount...
const callback = (props) => props.actions.hello(props.person);
export default Logic(HOC(callback)(SillyComponent))
If you use <SillyComponent person="Bob"/>
somewhere, it will dispatch the action when it mounts, but workers.handleGreeting
will never run.
Given a simple kea logic definition applied to a component:
const ImportQuoteLogic = kea({
actions: () => ({
selectFile: (fileObj: File) => ({fileObj}),
cancelImport: () => ({}),
}),
reducers: ({actions}) => ({
quoteImport: [{}, PropTypes.object, {
[actions.selectFile]: (state, {fileObj}) => ({filename: fileObj.name}),
[actions.cancelImport]: state => ({}),
}],
}),
workers: {
handleFile: function* (action) {
console.log('process file');
yield call(console.log, 'process file', action.payload);
},
},
start: function* () {
console.log('start');
yield call(console.log, 'start');
},
takeEvery: ({actions, workers}) => {
console.log('returning action to worker mapping...');
return ({
[actions.selectFile]: workers.handleFile,
});
},
});
The sagas don't run. start
never prints to the console; neither does 'returning action to worker mapping'. The actions and reducers all work (as observed in the redux dev tools); just the sagas are ignored.
I have a few other kea-fied components that are behaving just fine, so it is not my overall kea setup. I feel like it must be just staring me in the face, but I've been at this for hours now and I'm getting nowhere.
Hi,
I'm really liking KeaJS and the abstractions that it brings to our code.
However I would appreciate it if you could provide examples on how to integrate Apollo & GraphQL (perhaps use Graph.cool service for the backend) with Kea JS. How do we go about using HOC from apollo library within sagas inside Kea?
Also I'm wondering if Kea would play nice with stateless functional components (so that I can use recompose helper utils instead of using the Kea decorator syntax)?
(I'm still new to Redux/Sagas etc so please bear with me)
Thanks!
UMD build will be very convenient, e.g. if I want to try out the library on codepen.
I am running into this error on v0.20.5
when trying to use the connect
functionality, following the example in the docs.
Uncaught TypeError: Cannot read property 'inline-0' of undefined
Importing a logic from a separate file and applying it in its entirety to a component works fine. However, trying to connect specific actions or props to a component fails. I've tried connecting using a decorator, with the shorthand syntax (connect(options)
), and with the long syntax (kea({ connect: { ... } })
, but i get the same error in all cases.
I am able to reproduce this in a simple Gist. Is there a step that i'm missing to make connect()
work or is this a bug in kea? I noticed that there has been some recent development activity, so maybe the docs are just outdated.
Please let me know if there is anything you need me to clarify about what is happening.
Thanks!
Edit: Here's the full stack trace.
selectors.js:6 Uncaught TypeError: Cannot read property 'inline-0' of undefined
at concat.reduce (selectors.js:6)
at Array.reduce (<anonymous>)
at pathSelector (selectors.js:6)
at rootSelector (selectors.js:22)
at index.js:86
at Object.reducer1 (index.js:36)
at Object.keys.forEach.propKey (kea.js:317)
at Array.forEach (<anonymous>)
at kea.js:316
at Object.runComponentSelector [as run] (connectAdvanced.js:26)
at Connect.initSelector (connectAdvanced.js:178)
at new Connect (connectAdvanced.js:119)
at ReactCompositeComponent.js:294
at measureLifeCyclePerf (ReactCompositeComponent.js:75)
at ReactCompositeComponentWrapper._constructComponentWithoutOwner (ReactCompositeComponent.js:293)
at ReactCompositeComponentWrapper._constructComponent (ReactCompositeComponent.js:279)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:187)
at Object.mountComponent (ReactReconciler.js:45)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:370)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:257)
at Object.mountComponent (ReactReconciler.js:45)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:370)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:257)
at Object.mountComponent (ReactReconciler.js:45)
at mountComponentIntoNode (ReactMount.js:104)
at ReactReconcileTransaction.perform (Transaction.js:143)
at batchedMountComponentIntoNode (ReactMount.js:126)
at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:143)
at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
at Object.batchedUpdates (ReactUpdates.js:97)
at Object._renderNewRootComponent (ReactMount.js:319)
at Object._renderSubtreeIntoContainer (ReactMount.js:401)
at Object.render (ReactMount.js:422)
at Object../src/index.js (index.js:79)
at __webpack_require__ (bootstrap 7abea5da1d167805669e:659)
at fn (bootstrap 7abea5da1d167805669e:85)
at Object.0 (index.js:80)
at __webpack_require__ (bootstrap 7abea5da1d167805669e:659)
at ./node_modules/ansi-regex/index.js.module.exports (bootstrap 7abea5da1d167805669e:708)
at bundle.js:712
For some reason I am seeing this behaviour that every time anything in any redux state changes the root prop also changes. It becomes impossible to do this:
shouldComponentUpdate(nextProps) {
return !shallowEqual(this.props, nextProps);
}
Even though the other props pass this check the root from kea does not.
Types can be enforced by a type system like Flow or TypeScript, and there's no real benefit (that I am aware of) to be gained in production from including them.
can they be made optional? that way they can be stripped using a babel codemode for example when building for production.
Hey, I think this part of the kea.js.org website needs to be upgraded:
The first thing I'd do is rework the bottom part into something like what inferno and other similar sites have:
Anyone up for the task? :)
If you want to play with the website, just clone it, yarn
, yarn start
and http://localhost:2000
Hey folks,
I've just trying to differentiate Kea with some other frameworks/libraries using Redux as a base but could not find any source using preact as its view layer integrated with Preact. Is there any plan to do such an example and step-by-step guide using Kea with Preact?
Update: I have tried with a sample app and got he following:
ERROR in ./~/kea/lib/kea/index.js
Module not found: Error: Can't resolve 'react-redux' in '/<repo-path>/node_modules/kea/lib/kea'
@ ./~/kea/lib/kea/index.js 52:18-40
@ ./~/kea/lib/index.js
@ ./src/containers/some-container.js
@ ./src/components/app.js
@ ./src/index.js
@ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src
Note: I am using preact-redux.
Cheers
Baris
Hi Marius,
First, Thanks a lot for keajs.
I am trying to use connect along with key.
I ran into an issue??
It is most likely not an issue, may be I just do not know how to use it.
Example 1: props works inside connect
// with-visible.js
export default kea({
path: () => ['scenes', 'App', 'Alert'],
actions: () => ({
show: (args) => ({ ...args, type: 'show' }),
hide: (args) => ({ ...args, type: 'hide' }),
}),
reducers: ({ actions, key }) => ({
visible: [true, PropTypes.bool, {
[actions.show]: () => true,
[actions.hide]: () => false,
}]
})
});
import withVisible from './with-visible';
const options = {
actions: [
withVisible, [
'show',
'hide'
]
],
props: [
withVisible, [
'visible',
],
],
};
Example 2: props does not work inside connect
export default kea({
key: ({id}) => id,
path: (key) => ['scenes', 'App', 'Alert', key],
actions: () => ({
show: (args) => ({ ...args, type: 'show' }),
hide: (args) => ({ ...args, type: 'hide' }),
}),
reducers: ({ actions, key }) => ({
visible: [true, PropTypes.bool, {
[actions.show]: (state, payload) => payload.key === key ? true : state,
[actions.hide]: (state, payload) => payload.key === key ? false : state,
}]
})
});
import withVisible from './with-visible';
const options = {
actions: [
withVisible, [
'show',
'hide'
]
],
props: [
/*
// This does not work because withVisible is not a singleton (has a key)
withVisible, [
'visible',
],
*/
(state) => {
return state.scenes.App &&
state.scenes.App.Alert &&
state.scenes.App.Alert.Alert1 &&
state.scenes.App.Alert.Alert2 ? state.scenes.App.Alert: {
Alert1: { visible: true },
Alert2: { visible: true }
}
}, [
'Alert1',
'Alert2'
]
],
};
What is the idiomatic way of doing example 2 using connect when logic is not a singleton (has a key)?
You can see the complete source here:
https://github.com/codingarchitect/component-state-kea/blob/master/src/with-visible.js#L5
https://github.com/codingarchitect/component-state-kea/blob/master/src/App.jsx#L13-L32
Thanks,
I'm having this error on my console
console.error node_modules/kea/lib/scene/store.js:278
[KEA-LOGIC] Path starting with "components" is not connected to the reducer tree! Make sure to call keaReducer() before any calls to kea() take place! [ 'components', 'auth', 'index' ]
I've tried following your tests by doing this
import {keaReducer} from 'kea';
const scenesReducer = keaReducer('components');
let reducerState1;
beforeEach(() => {
reducerState1 = scenesReducer({}, { type: 'discard' });
});
it('should connect to reducer tree', () => {
expect(reducerState1).toEqual({});
});
how can I fix it?
Another issue is testing using constants
export default kea({
path: () => ['components', 'auth', 'index'],
constants: () => [ 'LOGIN_REQUEST'],
actions: ({constants}) => ({
requestLogin: creds => ({
type: constants.LOGIN_REQUEST,
creds
})
})
})
it('should create an action to request login', () => {
const credentials = {
username: '[email protected]',
password: 'test123'
};
const expectedAction = {
type: constants.LOGIN_REQUEST,
payload: {
creds: credentials
}
};
expect(actions.requestLogin(credentials)).toEqual(expectedAction);
});
Difference:
- Expected
+ Received
@@ -2,8 +2,9 @@
"payload": Object {
"creds": Object {
"password": "test123",
"username": "[email protected]",
},
+ "type": "LOGIN_REQUEST",
},
- "type": "LOGIN_REQUEST",
+ "type": "request login (components.auth.index)",
}
So the constant is inside the payload and the action type follow the action name.
So I was wondering why it can't match the constant in this case?
Thank for your support
When I use hot reloading for react, whenever it fires, koa will throw this error [KEA-LOGIC] Already created action "set group (app.materials)"
for each action. Also, the actions will not work from then on, only on a hard reload F5 of the website it'll work again.
I wonder if you could change the behaviour of kea to overwrite actions so this works, or do you have another idea how to resolve this?
I find the README is lacking this key concept explanation. So raise this issue here.
I'm currently using a solution of redux + thunk + redux-promise-middleware,
why do I want to use kea and when?
I would like to try kea and have an issue installing dependencies on ubuntu 14.04 (x64) using node v8.1.4 (npm v5.3.0).
I get this error : Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
How can we deal with it ?
Hi,
I tried to install kea
and configure it like described in step 1 https://kea.js.org/guide/installation but i'm getting error:
./node_modules/kea/src/logic/_deprecated.js
91:9-12 "export 'createKeaStore' (imported as 'cks') was not found in '../scene/store'
This happened using version 0.19.12
.
I'm using module
main field https://github.com/keajs/kea/blob/master/package.json#L8 via webpack
+ babel
Error is coming from https://github.com/keajs/kea/blob/master/src/logic/_deprecated.js#L3
and export is actually missing in https://github.com/keajs/kea/blob/master/src/scene/store.js
But https://github.com/keajs/kea/blob/master/src/scene/index.js#L6 is also trying to export
So it looks like createKeaStore
is missing in ./src/scene/store.js`
Connecting Kea to a component that contains routes does not work properly, the routes are not matched.
import React, { Component } from 'react'
import { kea } from 'kea'
const logic = kea({})
class _Wrapper extends Component {
render() {
return(
<div>{this.props.children}</div>
)
}
}
const Wrapper = logic(_Wrapper) // switch routes does not work
//const Wrapper = _Wrapper // switch routes works
const App = () => (
<ConnectedRouter history={history}>
<Wrapper>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/foo">Foo</Link></li>
<li><Link to="/bar">Bar</Link></li>
</ul>
<Route exact path="/" component={Home} />
<Route path="/foo" component={Foo} />
<Route path="/bar" component={Bar} />
</Wrapper>
</ConnectedRouter>
)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.