Skip to Content
GuidesSicilian Provider

SicilianProvider and useSicilianContext

Previously, the properties returned by the register function were passed directly as props to the input tag or Input component using the spread operator. This caused the entire form to re-render when the input was changed.

<input {...register('email', validator.email)}>

To suppress this, instead of using the spread operator, you should pass register and name as props and combine them within the Input component. The problem of this solution is that register and name are inferred as very narrow types, making it quite cumbersome to pass them as props to the component.

 

To address these issues, Sicilian version 2.0.0 introduced the SicilianProvider component and the useSicilianContext function. As mentioned earlier, these are implemented internally using the Context API, and since they only pass predefined values and functions.

The SicilianProvider component accepts a value object as a prop, which contains five values and methods: register, name, validate, type, getValues, and getErrors. Among these, register and name are required, and based on the type of register, the valid string types for name are automatically inferred.

스크린샷 2024-09-11 오후 8 16 46

 

The other props except register and name can be provided optionally. and values and functions provided in this way can be retrieved using the useSicilianContext function. If the SicilianProvider component is not present in the parent node, the useSicilianContext function will throw an error like the following:

스크린샷 2024-09-11 오후 8 03 26

 

If you attempt to access the validate, getValues, or getErrors props through the useSicilianContext function without providing them to the SicilianProvider component, here’s what happens:

  • For validate and type, it’s fine because its type includes undefined, so it can be accessed without issues.
  • For getValues and getErrors, if you try to access these functions through useSicilianContext without providing them in the SicilianProvider component, what you actually get is not the getValues or getErrors functions themselves but functions that log error messages to the console. These error messages will help you identify which component is attempting to use getValues and getErrors without having been provided these functions as props.
스크린샷 2024-09-11 오후 7 32 53

Here is a simple example of the Input component using SicilianProvider and useSicilianContext:

import { register, getValues, getErrors } from "@/hooks/FormController/signUp.ts" import { SicilianProvider } from "sicilian/provider" export default function Home() { { ... } return ( <> { ... } <SicilianProvider value={{ register, name: "email", getErrors }}> <Input /> </SicilianProvider> <SicilianProvider value={{ register, name: "password", getErrors }}> <Input /> </SicilianProvider> { ... } </> ) }
import { useSicilianContext } from "sicilian/provider" export default function Input({className, ...props}: InputHTMLAttributes<HTMLInputElement>) { const { register, name, validate, getErrors } = useSicilianContext() const errorMessage = getErrors(name) return ( <> <input {...props} {...register({ name, validate })} className={clsx(styles.input, className)} /> <Show when={!!errorMessage}> {errorMessage} </Show> </> ); }

Here is an example of a login form using Sicilian version 1, inspected with Chrome’s React Developer Tools. As shown, even when typing into the email input, you can see that the entire form is repeatedly re-rendering.

스크린샷 2024-09-11 오후 7 32 53

In the other hand, here is the login form recreated using the latest version looks as follows. By utilizing SicilianProvider, useSicilianContext, and the getErrors function, which allows subscribing to only a portion of the overall state, you can ensure that only the Input component being typed into is re-rendered, rather than the entire form being re-rendered.

스크린샷 2024-09-11 오후 7 32 53
Last updated on