Our First Story
例えば、ホームページでブログ記事の最初の2〜3文を要約して表示し、全文を見るにはクリックする必要があるとします。
まず、この機能を実現するよう Article
コンポーネントを更新してみましょう:
- JavaScript
- TypeScript
import { Link, routes } from '@redwoodjs/router'
const truncate = (text, length) => {
return text.substring(0, length) + '...'
}
const Article = ({ article, summary = false }) => {
return (
<article className="mt-10">
<header>
<h2 className="text-xl text-blue-700 font-semibold">
<Link to={routes.article({ id: article.id })}>{article.title}</Link>
</h2>
</header>
<div className="mt-2 text-gray-900 font-light">
{summary ? truncate(article.body, 100) : article.body}
</div>
</article>
)
}
export default Article
import { Link, routes } from '@redwoodjs/router'
import type { Post } from 'types/graphql'
const truncate = (text: string, length: number) => {
return text.substring(0, length) + '...'
}
interface Props {
article: Omit<Post, 'createdAt'>
summary?: boolean
}
const Article = ({ article, summary = false }: Props) => {
return (
<article className="mt-10">
<header>
<h2 className="text-xl text-blue-700 font-semibold">
<Link to={routes.article({ id: article.id })}>{article.title}</Link>
</h2>
</header>
<div className="mt-2 text-gray-900 font-light">
{summary ? truncate(article.body, 100) : article.body}
</div>
</article>
)
}
export default Article
コンポーネントに追加の summary
props を渡して、要約だけを表示するか、全体を表示するかを知らせます。デフォルトは false
で、既存の挙動を維持 -- つまり常に本文を表示します。
それではStorybook で summary
ストーリーを作りましょう。これは generated
と同じように Article
コンポーネントを使うものの、 新しい summary
props を追加したものです。
サンプルポストの内容を定数に格納し、両方のストーリーで使うことにします。また、両者の違いを明確にするために、generated
を full
にリネームします:
- JavaScript
- TypeScript
import Article from './Article'
const ARTICLE = {
id: 1,
title: 'First Post',
body: `Neutra tacos hot chicken prism raw denim, put a bird on it enamel pin post-ironic vape cred DIY. Street art next level umami squid. Hammock hexagon glossier 8-bit banjo. Neutra la croix mixtape echo park four loko semiotics kitsch forage chambray. Semiotics salvia selfies jianbing hella shaman. Letterpress helvetica vaporware cronut, shaman butcher YOLO poke fixie hoodie gentrify woke heirloom.`,
}
export const full = () => {
return <Article article={ARTICLE} />
}
export const summary = () => {
return <Article article={ARTICLE} summary={true} />
}
export default { title: 'Components/Article' }
import Article from './Article'
const ARTICLE = {
id: 1,
title: 'First Post',
body: `Neutra tacos hot chicken prism raw denim, put a bird on it enamel pin post-ironic vape cred DIY. Street art next level umami squid. Hammock hexagon glossier 8-bit banjo. Neutra la croix mixtape echo park four loko semiotics kitsch forage chambray. Semiotics salvia selfies jianbing hella shaman. Letterpress helvetica vaporware cronut, shaman butcher YOLO poke fixie hoodie gentrify woke heirloom.`,
}
export const full = () => {
return <Article article={ARTICLE} />
}
export const summary = () => {
return <Article article={ARTICLE} summary={true} />
}
export default { title: 'Components/Article' }
変更を保存するとすぐにStorybookのストーリーが更新され、エラーが表示される場合があります:もう表示されるべき "Generated" なストーリーはありません!左側のツリーで "Article" を展開すると、 "Full" バージョンが表示されるはずです。 "Summary" をクリックすると、その違いがわかります:
Displaying the Summary
素晴らしい!では完璧に仕上げるために、ブログ記事を表示するホームページでこの要約を使ってみましょう。実際のホームページでは、参照は Article
コンポーネントではなく ArticlesCell
にあります。このように summary
props を追加して、Storybook で結果を確認しましょう:
- JavaScript
- TypeScript
import Article from 'src/components/Article'
export const QUERY = gql`
query ArticlesQuery {
articles: posts {
id
title
body
createdAt
}
}
`
export const Loading = () => <div>Loading...</div>
export const Empty = () => <div>Empty</div>
export const Failure = ({ error }) => <div>Error: {error.message}</div>
export const Success = ({ articles }) => {
return (
<div className="space-y-10">
{articles.map((article) => (
<Article article={article} key={article.id} summary={true} />
))}
</div>
)
}
import Article from 'src/components/Article'
import type { ArticlesQuery } from 'types/graphql'
import type { CellSuccessProps, CellFailureProps } from '@redwoodjs/web'
export const QUERY = gql`
query ArticlesQuery {
articles: posts {
id
title
body
createdAt
}
}
`
export const Loading = () => <div>Loading...</div>
export const Empty = () => <div>Empty</div>
export const Failure = ({ error }: CellFailureProps) => (
<div>Error: {error.message}</div>
)
export const Success = ({ articles }: CellSuccessProps<ArticlesQuery>) => {
return (
<div className="space-y-10">
{articles.map((article) => (
<Article article={article} key={article.id} summary={true} />
))}
</div>
)
}
要約を実装した新しい一覧を見るにはストーリーをチェックしてください:
そして、実際のサイトを開くと、ここも概要が表示されています:
ArticleCell
での Article
( summary
props を含まないもの) の元々の使い方が、切り捨てられた(要約された)バージョンだけでなく、全体の投稿をレンダリングすることを再確認することができます:
Storybookは、コンポーネントを分離して作成および変更することを容易にし、実際にReactアプリケーションを構築する際の一般的なベストプラクティスにきちんと則るのに役立ちます:コンポーネントは、送信される props を変更するだけで自己完結し再利用可能でなければなりません。