|  | 
|  | 1 | +--- | 
|  | 2 | +title: useReactiveValue() | 
|  | 3 | +layout: API | 
|  | 4 | +--- | 
|  | 5 | +## Storing Primitives | 
|  | 6 | +The `useReactiveValue` hook combined with the `ReactiveValue<T>` C# class allows you to hook into individual properties of an object. | 
|  | 7 | + | 
|  | 8 | +`ReactiveValue`'s are set via the `.Value` property, which will automatically trigger any watching hooks. | 
|  | 9 | + | 
|  | 10 | +For example, this `Player` `MonoBehaviour` could be stored in Globals: | 
|  | 11 | + | 
|  | 12 | +```csharp | 
|  | 13 | +// C# | 
|  | 14 | +public class Player: MonoBehaviour { | 
|  | 15 | + | 
|  | 16 | +    public ReactRendererBase renderer;  | 
|  | 17 | + | 
|  | 18 | +    // special class for communicating between React and Unity | 
|  | 19 | +    public ReactiveValue<float> Score = new ReactiveValue<float>(); | 
|  | 20 | +    public ReactiveValue<int> Deaths = new ReactiveValue<int>(); | 
|  | 21 | +    public ReactiveValue<int> Kills = new ReactiveValue<int>(); | 
|  | 22 | + | 
|  | 23 | +    void Awake() { | 
|  | 24 | +      renderer.Globals["Player"] = this; | 
|  | 25 | +    } | 
|  | 26 | + | 
|  | 27 | +    // set ReactiveValue with .Value | 
|  | 28 | +    public void AddScore(float score) { | 
|  | 29 | +      Score.Value += score; | 
|  | 30 | +    } | 
|  | 31 | + | 
|  | 32 | +    /* Rest of Player code */ | 
|  | 33 | +} | 
|  | 34 | +``` | 
|  | 35 | +And then accessed in React via the hook: | 
|  | 36 | +```js | 
|  | 37 | +// JS | 
|  | 38 | +export function ScoreTracker() { | 
|  | 39 | +  const {Player} = useGlobals(); | 
|  | 40 | +  // will trigger a re-render when Score changes | 
|  | 41 | +  const score = useReactiveValue(Player.Score); | 
|  | 42 | + | 
|  | 43 | +  return (<text>{score}</text>) | 
|  | 44 | +} | 
|  | 45 | +``` | 
|  | 46 | + | 
|  | 47 | +## Non-Primitive Types | 
|  | 48 | +For Lists and Dictionaries, there are the `ReactiveList<T>` and `ReactiveRecord<T>` classes. | 
|  | 49 | + | 
|  | 50 | + Normal `ReactiveValue`'s can also hold non-primitive objects, but they will only trigger a re-draw if the actual object reference changes.  | 
|  | 51 | +  | 
|  | 52 | + It's recommended to either use a `ReactiveValue` per field (see above), an immutable type like `record`, or a secondary variable for tracking the state change (see below). | 
|  | 53 | + | 
|  | 54 | +### Method 1: ReactiveList | 
|  | 55 | +Say we want to store a Player's inventory for drawing on the UI. The simplest approach is to use a `ReactiveList`: | 
|  | 56 | + ```csharp | 
|  | 57 | + // C# | 
|  | 58 | + /* Player class continued */ | 
|  | 59 | + { | 
|  | 60 | +  // track a list of all items in the inventory | 
|  | 61 | +    public ReactiveList<Item> Inventory = new ReactiveList<Item>(); | 
|  | 62 | + | 
|  | 63 | +    public void AddItem(Item item) { | 
|  | 64 | +      // will trigger re-renders as needed | 
|  | 65 | +      Inventory.Add(item); | 
|  | 66 | +    } | 
|  | 67 | + } | 
|  | 68 | + ``` | 
|  | 69 | + ```js | 
|  | 70 | + // JS | 
|  | 71 | + export function DrawItems() { | 
|  | 72 | +  const {Player} = useGlobals(); | 
|  | 73 | +  const itemList = useReactiveValue(Player.Inventory); | 
|  | 74 | +  // return drawn items | 
|  | 75 | + } | 
|  | 76 | + ``` | 
|  | 77 | + | 
|  | 78 | + ### Method 2: Secondary Variable | 
|  | 79 | + Now we want to add more functionality to the inventory, and it can no longer be just a list. Instead it is an `Inventory` object, and we track changes to its internal state with a counter variable. | 
|  | 80 | + ```csharp | 
|  | 81 | + /* Player class continued */ | 
|  | 82 | + { | 
|  | 83 | +    public ReactiveValue<int> InventoryChanges = new ReactiveValue<int>();  | 
|  | 84 | +    public InventorySystem Inventory; | 
|  | 85 | + | 
|  | 86 | +    public void AddItem(Item item) { | 
|  | 87 | +      // trigger re-render with counter instead | 
|  | 88 | +      InventoryChanges.Value += 1; | 
|  | 89 | +      Inventory.Add(item); | 
|  | 90 | +    } | 
|  | 91 | + } | 
|  | 92 | + ``` | 
|  | 93 | +```js | 
|  | 94 | +// JS | 
|  | 95 | +export function DrawItems() { | 
|  | 96 | +  const {Player} = useGlobals(); | 
|  | 97 | + | 
|  | 98 | +  // re-render based on the counter | 
|  | 99 | +  const _invChanges = useReactiveValue(Player.InventoryChanges); | 
|  | 100 | + | 
|  | 101 | +  // reference the Inventory object and call functions | 
|  | 102 | +  const inventory = Player.Inventory; | 
|  | 103 | +  const itemList = inventory.ListItems(); | 
|  | 104 | + | 
|  | 105 | +  // call other functions from Inventory class | 
|  | 106 | +   | 
|  | 107 | +  // return drawn items | 
|  | 108 | +} | 
|  | 109 | +``` | 
0 commit comments