[Example #3] Fetch Data By User Input
by redneckz
HTML
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>
<script src="https://unpkg.com/@redneckz/react-rxjs@0.0.4/dist/index.min.js"></script>
CSS
.post__title {
font-size: large;
font-weight: bold;
}
Babel + JSX
const { from } = rxjs;
const { map, distinctUntilChanged, debounceTime, switchMap } = rxjs.operators;
const { reactive, handle } = ReactRxjs;
const PostsSearchForm = reactive(
() => from(fetchUsers()).pipe(
map(possibleUsers => ({ possibleUsers }))
)
)(({ author, onChangeAuthor, possibleUsers = [] }) => (
<section>
<input value={author} onChange={onChangeAuthor} list="possibleUsers" />
<datalist id="possibleUsers">
{possibleUsers.map(({ username, name }) => (
<option value={username} label={name} />
))}
</datalist>
</section>
));
const Posts = reactive(
props$ => props$.pipe(
map(({ author }) => author),
distinctUntilChanged(),
debounceTime(300),
switchMap(fetchPostsByAuthor),
map(posts => ({ posts }))
)
)(
({ posts = [] }) => (
<section>
{posts.map(({ id, title, body }) => (
<Post key={id} title={title}>{body}</Post>
))}
{posts.length === 0 && <strong>Nothing found</strong>}
</section>
)
);
const FilteredPosts = reactive(
handle('onChangeAuthor',
map(({ target: { value } }) => ({ author: value }))
)
)(
({ author, onChangeAuthor }) => (
<section>
<PostsSearchForm author={author} onChangeAuthor={onChangeAuthor} />
<hr />
<Posts author={author} />
</section>
)
);
function Post({ title, children }) {
return (
<article>
<header className="post__title">{title}</header>
<p>{children}</p>
</article>
);
}
async function fetchUsers() {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
return response.json();
}
async function fetchUserByName(username) {
const response = await fetch(
`https://jsonplaceholder.typicode.com/users?username=${username}`
);
const [user] = await response.json();
return user;
}
async function fetchPostsByAuthor(author) {
const { id: authorId } = await fetchUserByName(author) || {};
if (!authorId) return [];
const response = await...