0.0.1 • Published 5 years ago
react-akita v0.0.1
React Akita
React bindings for Akita.
Example
Let's implement a counter.
JavaScript
AkitaState.js (Shared)
import { Store, StoreConfig, Query } from "@datorama/akita";
export function createInitialState() {
return {
count: 0,
};
}
@StoreConfig({ name: "count" })
class CountStore extends Store {
constructor() {
super(createInitialState());
}
}
class CountQuery extends Query {
count$ = this.select((state) => state.count);
}
class CountService {
constructor(store) {
this.store = store;
}
increment() {
this.store.update({ count: this.store.getValue().count + 1 });
}
}
export const store = new CountStore();
export const query = new CountQuery(store);
export const service = new CountService(store);
Akita Only
App.js
import React from "react";
import "./App.css";
import AkitaCounter from "./AkitaCounter";
function App() {
return (
<div className="App">
<AkitaCounter />
</div>
);
}
export default App;
AkitaCounter.js
import React from "react";
import { query, service } from "./AkitaState";
import { untilUnmounted } from "./take-until";
export default class AkitaCounter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
componentDidMount() {
query.count$
.pipe(untilUnmounted(this))
.subscribe((count) => this.setState({ count }));
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => service.increment()}>Click me</button>
</div>
);
}
}
take-until.js (Helper)
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
export const untilUnmounted = (
componentInstance,
destroyMethodName = "componentWillUnmount"
) => (source) => {
const originalDestroy = componentInstance[destroyMethodName];
if (!componentInstance["__takeUntilDestroy"]) {
componentInstance["__takeUntilDestroy"] = new Subject();
componentInstance[destroyMethodName] = function () {
typeof originalDestroy === "function" &&
originalDestroy.apply(this, arguments);
componentInstance["__takeUntilDestroy"].next(true);
componentInstance["__takeUntilDestroy"].complete();
};
}
return source.pipe(takeUntil(componentInstance["__takeUntilDestroy"]));
};
Akita with React Akita
App.js
import React from "react";
import "./App.css";
import ReactAkitaCounter from "./ReactAkitaCounter";
import { query, service } from "./AkitaState";
import { Provider } from "react-akita";
const rootQuery = {
counterQuery: query,
};
const rootService = {
counterService: service,
};
function App() {
return (
<div className="App">
<Provider rootQuery={rootQuery} rootService={rootService}>
<ReactAkitaCounter />
</Provider>
</div>
);
}
export default App;
ReactAkitaCounter.js
import React from "react";
import { connect } from "react-akita";
function ReactAkitaCounter(props) {
return (
<div>
<p>You clicked {props.count} times</p>
<button onClick={props.increment}>Click me</button>
</div>
);
}
const mapQueryToProps = ({ counterQuery }) => ({ count: counterQuery.count$ });
const mapServiceToProps = ({ counterService }) => ({
increment: () => counterService.increment(),
});
export default connect(mapQueryToProps, mapServiceToProps)(ReactAkitaCounter);
As you may see we not only decreased amount of the code we need to write but also we were able to use a function component instead a class component.
0.0.1
5 years ago