Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs Restructure #40

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions docs/examples/InvalidateQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { bind, Subscribe } from "@react-rxjs/core"
import { createSignal } from "@react-rxjs/utils"
import React, { useRef } from "react"
import { concat, defer } from "rxjs"
import { concatMap, switchMap } from "rxjs/operators"

const { getTodos, postTodo } = (() => {
let todos = [
{
id: 0,
title: "Grocery shopping",
},
]

return {
getTodos: async () => todos,
postTodo: async (todo) => {
todos = [
...todos,
{
id: todos[todos.length - 1].id + 1,
title: todo,
},
]
},
}
})()

const [todoPost$, addTodo] = createSignal<string>()

const todoResult$ = todoPost$.pipe(concatMap(postTodo))

const [useTodos] = bind(
// When do we need to request todos?
concat(
// 1. One single time when starting
defer(getTodos),
// 2. Every time we have created a new todo
todoResult$.pipe(switchMap(getTodos)),
),
[],
)

function Todos() {
const todos = useTodos()

const ref = useRef<HTMLInputElement>()
const handleAddClick = () => {
addTodo(ref.current!.value)
ref.current!.value = ""
ref.current!.focus()
}

return (
<div>
<input type="text" defaultValue="Do Laundry" ref={ref} />
<button onClick={handleAddClick}>Add Todo</button>

<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
</div>
)
}

export default function InvalidateQuery() {
return (
<Subscribe fallback={<div>Loading...</div>}>
<Todos />
</Subscribe>
)
}
15 changes: 15 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Features
---
Comment on lines +1 to +3
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to have a section highlighting these few features.... things like TS support, React Native, etc., but I feel this feels a bit empty. Dunno


- Build truly reactive state.
- Makes code-splitting simple.
- Simplifies code navigability.
- First-class support for React Suspense.
- First-class support for Error boundaries.
- Completely decentralized store.
- Built in Typescript.
- Works with any React renderer (React DOM, React Native, etc.).
- No external dependencies.
- Extremely light: 3.4kB parsed, 1.5kB gziped.
- Thin API.
99 changes: 0 additions & 99 deletions docs/getting-started.md

This file was deleted.

92 changes: 92 additions & 0 deletions docs/quick-start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
title: Quick Start
---

import CharacterCounter from "./examples/CharacterCounter"
import BrowserOnly from '@docusaurus/BrowserOnly';

## Installation

React-RxJS is published in npm as `@react-rxjs/core`.
We also publish a recommended `@react-rxjs/utils` package with some useful functions to build reactive state streams.

```sh
npm i rxjs @react-rxjs/core @react-rxjs/utils
```

or using yarn

```sh
yarn add rxjs @react-rxjs/core @react-rxjs/utils
```

## Usage

```tsx
import { map } from "rxjs/operators"
import { bind, Subscribe } from "@react-rxjs/core"
import { createSignal } from "@react-rxjs/utils"

// A signal is an entry point to react-rxjs. It's equivalent to using a subject
const [textChange$, setText] = createSignal<string>()

// bind returns a hook to get the value of the observable.
const [useText, text$] = bind(textChange$, "")

// And it also returns an observable so we can compose this state with other observables
// in here we're making a derived state by calculating the text$'s length.
const [useCharCount, charCount$] = bind(
text$.pipe(
map((text) => text.length)
)
)

function TextInput() {
// Just use the hook!
const text = useText()

return (
<div>
<input
type="text"
value={text}
placeholder="Type something..."
onChange={
// And trigger the signal
(e) => setText(e.target.value)
}
/>
<br />
Echo: {text}
</div>
)
}

function CharacterCount() {
const count = useCharCount()

return <>Character Count: {count}</>
}

function CharacterCounter() {
// `Subscribe` manages the subscription lifetime of its children
return (
<Subscribe>
<TextInput />
<CharacterCount />
</Subscribe>
)
}
```

### Interactive result

<BrowserOnly>
{() => <CharacterCounter />}
</BrowserOnly>

## There's more!

This is just a simple example of two components sharing a synchronous state.

React-RxJS gets even more fun when you start using asynchronous state, leveraging Suspense and enhancing code-splitting!
71 changes: 71 additions & 0 deletions docs/recipes/invalidate-query.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: Invalidate Query
---

import InvalidateQuery from "../examples/InvalidateQuery"
import BrowserOnly from '@docusaurus/BrowserOnly';

```tsx
import { bind, Subscribe } from "@react-rxjs/core"
import { createSignal } from "@react-rxjs/utils"
import { concat, defer } from "rxjs"
import { concatMap, switchMap } from "rxjs/operators"
import { getTodos, postTodo } from "../my-api"

const [todoPost$, addTodo] = createSignal<string>()

const todoResult$ = todoPost$.pipe(
concatMap(postTodo)
)

const [useTodos] = bind(
// When do we need to request todos?
concat(
// 1. One single time when starting
defer(getTodos),
// 2. Every time we have created a new todo
todoResult$.pipe(
switchMap(getTodos)
)
),
[]
)

function Todos() {
const todos = useTodos()

const ref = useRef<HTMLInputElement>()
const handleAddClick = () => {
addTodo(ref.current!.value)
ref.current!.value = ""
ref.current!.focus()
}

return (
<div>
<input type="text" defaultValue="Do Laundry" ref={ref} />
<button onClick={handleAddClick}>Add Todo</button>

<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
</div>
)
}

function App() {
return (
<Subscribe>
<Todos />
</Subscribe>
)
}
```

### Interactive result

<BrowserOnly>
{() => <InvalidateQuery />}
</BrowserOnly>
4 changes: 2 additions & 2 deletions sidebars.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
someSidebar: {
Introduction: ["motivation", "core-concepts", "getting-started"],
Tutorial: ["tutorial/github-issues", "tutorial/todos"],
Introduction: ["motivation", "quick-start", "features"],
Recipes: ["recipes/invalidate-query"],
"API Reference": [
{
type: "category",
Expand Down
2 changes: 1 addition & 1 deletion src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ function Home() {
"button button--outline button--secondary button--lg",
styles.getStarted,
)}
to={useBaseUrl("docs/getting-started")}
to={useBaseUrl("docs/motivation")}
>
Get Started
</Link>
Expand Down