---
title: 'React'
description: "Learn how to use JSONEval-Rs in a standard React application (e.g. created with Vite or Create React App)."
navigation:
  icon: 'i-simple-icons-react'
seo:
  title: 'React'
  description: "Learn how to use JSONEval-Rs in a standard React application (e.g. created with Vite or Create React App)."
---

# Using JSONEval-Rs in React

This guide explains how to integrate `json-eval-rs` efficiently into a standard React application. 

Since `json-eval-rs` uses WebAssembly (WASM), the main challenge in browser environments is loading the WASM binary asynchronously before evaluation logic can run.

## 1. Installation

Install the web core API and the bundler target:

```bash
yarn add @json-eval-rs/webcore @json-eval-rs/bundler
```

## 2. Creating a Custom Hook

To comfortably use the evaluator in your React components, the best practice is to load it once asynchronously using a custom React Context and Hook, or just locally in a component if it's only needed in one place.

Let's create a `useJSONEval` hook that initializes the instance.

```typescript
// useJSONEval.ts
import { useState, useEffect } from 'react';
import { JSONEval } from '@json-eval-rs/webcore';

export function useJSONEval(schema: any) {
  const [evaluator, setEvaluator] = useState<JSONEval | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    let instance: JSONEval | null = null;
    let isMounted = true;

    async function init() {
      try {
        // Dynamically import the bundler module
        const wasmModule = await import('@json-eval-rs/bundler');
        
        if (isMounted) {
          instance = new JSONEval({
            schema: JSON.stringify(schema),
            wasmModule
          });
          setEvaluator(instance);
          setLoading(false);
        }
      } catch (err) {
        if (isMounted) {
          setError(err instanceof Error ? err : new Error(String(err)));
          setLoading(false);
        }
      }
    }

    init();

    return () => {
      isMounted = false;
      // ALWAYS free memory!
      if (instance) {
        instance.free();
      }
    };
  }, [schema]);

  return { evaluator, loading, error };
}
```

## 3. Using the Evaluator in a Component

With the hook created, you can now build a component that evaluates logic in real-time as the user types.

```tsx
import React, { useState } from 'react';
import { useJSONEval } from './useJSONEval';

const schema = {
  type: "object",
  properties: {
    age: {
      rules: {
        minValue: { value: 18, message: "You must be 18 or older to proceed." }
      }
    }
  }
};

export function AgeValidator() {
  const { evaluator, loading, error } = useJSONEval(schema);
  const [age, setAge] = useState<string>('');
  const [validationResult, setValidationResult] = useState<any>(null);

  const validate = async (value: string) => {
    if (!evaluator) return;
    
    const parsedAge = parseInt(value, 10);
    const result = await evaluator.validate({
      data: JSON.stringify({ age: isNaN(parsedAge) ? 0 : parsedAge })
    });
    
    setValidationResult(result);
  };

  const handleAgeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setAge(value);
    validate(value);
  };

  if (loading) return <div>Loading evaluation engine...</div>;
  if (error) return <div>Failed to load: {error.message}</div>;

  const hasError = validationResult?.has_error;

  return (
    <div>
      <h3>Age Validation</h3>
      <input 
        type="number" 
        value={age} 
        onChange={handleAgeChange}
        placeholder="Enter your age" 
      />
      
      {hasError && (
        <ul style={{ color: 'red' }}>
          {validationResult.errors.map((err: any, idx: number) => (
            <li key={idx}>{err.message}</li>
          ))}
        </ul>
      )}
      {!hasError && age !== '' && (
        <p style={{ color: 'green' }}>Looks good!</p>
      )}
    </div>
  );
}
```

### Key Takeaways for React

1. **Memory Management**: Notice the `instance.free()` inside the `useEffect` cleanup function. This is critical for preventing memory leaks when the component unmounts or the schema changes.
2. **Dynamic Importing**: We dynamically import `@json-eval-rs/bundler` because WebAssembly loading must occur asynchronously.
3. **State Updates**: Perform evaluations whenever user data state changes and capture the outputs.
