Gathering detailed insights and metrics for cartiv
Gathering detailed insights and metrics for cartiv
Gathering detailed insights and metrics for cartiv
Gathering detailed insights and metrics for cartiv
Super simple implementation of flux architecture. fully reactive, and much fun! No dispatcher, no reducers, no explicit actions, and definitely no ugly switch statements, would you believe that?
npm install cartiv
Typescript
Module System
Node Version
NPM Version
68.2
Supply Chain
97.9
Quality
74.9
Maintenance
100
Vulnerability
99.6
License
JavaScript (100%)
Total Downloads
5,749
Last Day
1
Last Week
1
Last Month
15
Last Year
200
51 Stars
111 Commits
5 Forks
5 Watching
4 Branches
3 Contributors
Latest Version
0.2.1
Package Id
cartiv@0.2.1
Size
10.86 kB
NPM Version
3.3.12
Node Version
4.2.2
Cumulative downloads
Total Downloads
Last day
0%
1
Compared to previous day
Last week
-66.7%
1
Compared to previous week
Last month
0%
15
Compared to previous month
Last year
-25.4%
200
Compared to previous year
2
Cartiv provides the simplest flux experience around. It is reactive like a react component, and have similar api, so if you know react - you'll understand this immediately. No annoying boilerplate and repetitions, better separation of concerns, and above all - it is simple and fun. Just try and you will see!
All you need is three files - react component
connected to (\controlled by) a store
and speaks with it via api
1/**** ./api.js ****/ 2import {createAPI} from 'cartiv'; 3export default createAPI(); 4 5 6/**** ./stores/TextStore.js ****/ 7import {createStore} from 'cartiv'; 8import api from '../api'; 9 10export default createStore({api, name: 'text'}, { 11 getInitialState(){ 12 return { title: 'Use Cartiv!', text: "It's the simplest flux you'll find"}; 13 }, 14 onChange(text){ 15 this.setState({text}); //setState... in a store! 16 }, 17 18}); 19 20 21/**** ./component/SimpleComp.js ****/ 22import textStore from '../stores/TextStore'; 23import api from '../api'; 24import {createConnector} from 'cartiv'; 25const connect = createConnector(React); 26 27@connect(textStore) //connect to states from store 28class SimpleComp extends Component { ... 29 onChange(e) { api.text.onChange(e.target.value) } //use the store's API 30 render() { 31 let {text, title} = this.state; //free magical state from the store 32 return ( 33 <div> 34 <h3>{title}</h3> 35 <input onChange={this.onChange} value={text} /> 36 <div> 37 ); 38 } 39});
#####Simple The goal of this library is to provide the easiest and simplest Flux experience, based on the the knowledge the react community has gained using older flux frameworks - Alt, Reflux and Redux. In Cartiv there are only Stores, Components and simple API object to communicate between them (forget about reducers, dispatchers, switch statements, global constants, action-creators etc). And yes, simplicity comes together with scalability and flexibility!
#####Reactive like React
Cartiv wishes to provide a fully reactive paradigm, while maintaining an API that is close as possible to React's API. React has managed to control the DOM from its components in an elegant and efficient way, using state, props and events for interactivity. Cartiv uses the same logic and language, to gain control of Components from Stores, with onSmthng
events, setState()
and other similar methods.
React component is "functional and reactive" - component(state) => view
(view is the outcome of the render function. if stateA === stateB, than the view will be also the same) .
Cartiv works the same way - store(state) => [component.state =>] view
. This FRP approach makes the implementation of time-travel and other cool things really simple.
#####separation of concerns The third polar of Cartiv's architecture is a correct separation of concerns - while in most flux implementations react components are structured in a hierarchical way, with parents and children, we believe that the view should be flat!. Every Component is on the same level (data wise), and then it is free to be moved around, without being dependent on its parent. Secondly, the view should not control the state of the app, it can call an event, that will eventually do something, but how or when - it's not the view's responsibility.
###architecture
Think about how a React component works:
1var SimpleComp = React.createClass({ 2 getInitialState() { 3 return {text: ''}; 4 }, 5 onChange(e) { 6 this.setState({text: e.target.value}); 7 // this is changing the state of the component. 8 // Whether it will affect any HTML elements or not is not important here. 9 }, 10 render() { 11 return ( 12 <div> 13 <h3>APP</h3> 14 <input onChange={this.onChange} value={this.state.text} /> 15 // before react, input had inner state. React grabbed that away from him to the component level 16 // so now input is "controlled" (value=), 17 // and it can only call an action (onChange) hoping it will change its controlled state 18 <div> 19 // notice that input's value is not dependent on any of its parents, 20 // you can just copy-paste it anywhere 21 </div> 22 </div> 23 ); 24 } 25});
Cartiv works the same way:
1$npm install cartiv --save
First - create an API :
1import {createAPI} from 'cartiv'; 2let API = createAPI(); 3export default API;
Then, create a store:
1import {createStore} from 'cartiv';
2import API from './Api';
3
4let textStore = createStore(
5 {
6 /* this is the store config: */
7 api: API, // listen to actions coming from api
8 name: 'text', // actions under 'text' property, e.g: api.text.onAction
9
10 // config.actions is optional,
11 // when not provided, all methods starting with 'on' will get called
12 <!--actions-->
13
14 // config.actions can either be an array of strings or a filter function.
15 actions: ['onChange', 'onSomethingElse'], // specify methods that will get called when equivalent action triggered
16 actions: function(action){return action.indexOf('get') > -1} //custom filter function
17
18 // config.syncActions is optional,
19 // when not provided, all methods starting with 'on' and ending with 'Sync' will get called synchronously
20 <!--syncActions-->
21
22 // config.syncActions can either be an array of strings or a filter function.
23 syncActions: ['onChangeSomething', 'onSomethingElse'], // specify methods that will get called when equivalent action triggered
24 syncActions: function(action){return action.indexOf('get') > -1} //custom filter function
25 // note that async (named or filtered) will override sync in case of conflict
26 },
27 {
28 /* this is the store definition: */
29 getInitialState(){ // same as React!
30 return {
31 text: 'Use Cartiv!',
32 }
33 },
34
35 onChange(textFromAction){
36 this.setState({text: textFromAction}); // same as React!
37 // setState changes the store state. Instead of `rendering` like react - this will `control`
38 // every connected component, that in turn will re-render
39 },
40
41 //async is easily done:
42 onGetDataFromServer(){
43 ajax.get(url).then((response)=>{
44 this.setState({serverData: response}); //when it'll be available, it will auto change every connected component
45 })
46 },
47
48 storeDidUpdate(prevState){ // same as React!
49 if(this.state.text !== prevState.text){console.log('text has changed'); }
50 }
51 });
52
53 createStore.allowHMR(module, textStore); //if you want to use webpack's hot-module-replacement
54 export default textStore;
55
Lastly, connect the component to the store:
1import {connect} from 'cartiv';
2import textStore from '../stores/textStore';
3import API from '../stores/Api';
4
5var SimpleComp = React.createClass({
6 mixins:[
7 connect(
8 textStore, // connect to the state of this Cartiv store
9 'text', // optional - connect only to this property of store's state.
10 // if not specified it will connect to all of the store's state
11 // more options:
12 // {text: inputText} // key is the state in store, val is the new name it will get in this component
13 // [{text: inputText}, 'someOtherState'...] //mixed list of previous options
14 'someName' // optional - the state will be available under this property. e.g: this.state.someName.text
15 ),
16 connect(otherStore, ['dogs', {cats: 'kittens'}]),
17 connect(thirdStore) // connect to every state of this store
18 ],
19 componentWillMount(){
20 API.text.onGetDataFromServer();
21 }
22 onChange(e) {
23 //this.setState({text: e.target.value}); //we don't use inner state any more
24 API.text.onChange(e.target.value)
25 },
26 render() {
27 return (
28 <div>
29 <h3>APP</h3>
30 <input onChange={this.onChange} value={this.state.text} />
31 //nothing changed here!
32 <div>
33 );
34 }
35});
If you are using react es6 classes, connect with es7 decorators */
1import {createConnector} from 'cartiv'; 2const connect = createConnector(React); 3 4//@viewPortDecorator // make sure other decorators that returns a Component (usually those who provide props) are above `connect` (since it controls state). 5@connect(textStore) //same signature as the mixin one 6@connect(otherStore, ['dogs', {'cats' : 'kittens'}]) 7//@autobind //other decorators could be anywhere 8class SimpleComp extends Component { ...
todoMVC example (copied from Redux repo, removed all the unnecessary parts and now it's Cartiv!)
Can you get any simpler?
(if you think you can - tell me your ideas - Cartiv is still young, and open for any thing that will help building react apps in the simplest possible way)
Cartiv sort of sounds like React + reactive. In Hebrew it means popcicle - which is just simple fun and cool, like this library!
#####Wath's next
connect
to server from store with sockects (Meteorizing react! yay!)###acknowledgments The internals of this library are based on reflux-core. This guarantees the stability of a mature framework with this new interface. I thank @spoike and the rest of the reflux community.
Special thanks to Yoni Levi for the logo's design
Cartiv has began as a mixin for reflux, that succeeded quite well. Later this was titled as a specification called super simple flux.
I've found out that Cartiv shares many ideas with om. great library, take a look.
No vulnerabilities found.
No security vulnerabilities found.