1.0.4 • Published 3 years ago

next-ssr-form v1.0.4

Weekly downloads
37
License
MIT
Repository
-
Last release
3 years ago

next-ssr-form

⚠️⚠️ This is an experimental library and is likely to be discontinued ⚠️⚠️

About

  • 🔨 Uses Next.js' getServerSideProps to receive post data and provide helpers to the page to render the form
  • 🎷 E2E type safety! TypeScript types inferred between client & server with all the nice autocomplete jazz
  • 🔐 Server-side data validation that's propagated to page props & your mutations' return values are inferred.
  • ☁️ Allows you to write data straight to the db with confidence
  • 🤘 Your page will wors without JS enabled (if you want it to)

(Peer) Dependencies:

  • zod for data validation
  • Formik as the form library

Table of contents:

Get started

ℹ️ Easiest thing to do is to look at the pages in examples/typescript.

0. Install

yarn add next-ssr-form zod formik

1. Add form to top of page

In a Next.js page/..:

export const createPostForm = createForm({
  schema: z.object({
    from: z.string().min(2),
    message: z.string().min(4),
  }),
  defaultValues: {
    message: "",
    from: "",
  },
  formId: "createPost",
});

2. Add mutation to getServerSideProps

export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
  const createPostProps = await createPostForm.getPageProps({
    ctx,
    /**
     * Your mutation function
     * - Will only be called when there's a POST to this form based on the `formId`
     * - 🌟 The `input` will be validated by the schema & the types inferred!
     */
    async mutation(input) {
      return DB.createPost(input);
    },
  });

  return {
    props: {
      // spread properties onto the prop
      ...createPostProps,
      posts: await DB.getAllPosts(),
    },
  };
};

3. Infer data types

type Props = InferGetServerSidePropsType<typeof getServerSideProps>;

export default function Home(props: Props) {
  // ...

Your data usage is now typesafe!

4. Use form

type Props = InferGetServerSidePropsType<typeof getServerSideProps>;
export default function Home(props: Props) {
  const [feedback, setFeedback] = useState(
    createPostForm.getFeedbackFromProps(props)
  );
  const initalValues = createPostForm.getInitialValues(props);
  const initialErrors = createPostForm.getInitialErrors(props);

  return (
    <>
      <h1>Normal http post (zod for validation)</h1>
      <p>
        Uses a standard <code>&lt;form&gt;</code> with the <code>action</code>
        -attribute to post to the same page. Form data is handled in{' '}
        <code>getServerSideProps</code> and feedback is passed through page
        props.
      </p>
      <h2>My guestbook</h2>
      {props.posts.map(item => (
        <article key={item.id}>
          <strong>
            From {item.from} at {item.createdAt}:
          </strong>
          <p className="message">{item.message}</p>
        </article>
      ))}
      <h3>Add post</h3>

      <form action={props.createPost.endpoints.action} method="post">
        <p className={`field ${initialErrors?.from ? 'field--error' : ''}`}>
          <label>
            Your name:
            <br />
            <input type="text" name="from" defaultValue={initalValues.from} />
            {initialErrors?.from && (
              <span className="field__error">{initialErrors.from}</span>
            )}
          </label>
        </p>
        <p className={`field ${initialErrors?.message ? 'field--error' : ''}`}>
          <label>
            Your message:
            <br />
            <textarea name="message" defaultValue={initalValues.message} />
            {initialErrors?.message && (
              <span className="field__error">{initialErrors.message}</span>
            )}
          </label>
        </p>
        <input type="submit" />

        <br />
        {feedback?.state === 'success' && (
          <span className="feedback success">Yay! Your entry was added</span>
        )}

        {feedback?.state === 'error' && (
          <>
            <span className="feedback error">
              Something went wrong: {feedback.error.message}. Full Error:{' '}
              <pre>
                {JSON.stringify(
                  {
                    ...feedback.error,
                    message: feedback.error.message,
                    stack: feedback.error.stack,
                  },
                  null,
                  4
                )}
              </pre>
            </span>
          </>
        )}
      </form>
    </>
  );
}

Author

@alexdotjs

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0-7

3 years ago

1.0.0-6

3 years ago

1.0.0-5

3 years ago

1.0.0-4

3 years ago

1.0.0-3

3 years ago

1.0.0-2

3 years ago

1.0.0-1

3 years ago

1.0.0-0

3 years ago

2.0.0

3 years ago

1.0.0

3 years ago

0.1.0

3 years ago

0.1.0-10

3 years ago

0.1.0-9

3 years ago

0.1.0-8

3 years ago

0.1.0-7

3 years ago

0.1.0-6

3 years ago

0.1.0-5

3 years ago

0.1.0-3

3 years ago

0.1.0-2

3 years ago

0.1.0-1

3 years ago