npm package: @peaca/proxy-state
Description: Simplified state management with proxy
Author: Joshua
Latest version: 0.0.2

# proxy-state

- A `$` prefix is used to denote its a proxy state (jquery is now gone, or at least for me).
- The preix makes proxy states be explicit as calling get/set of them will trigger aditional operations.
- `$` suffix is taken by Observerables by the way.

## use inside components

### local state management, offers another option other than `useState` `useReducer`

```jsx
import React from 'react';
import { useProxyState } from '@peaca/proxy-state';

const Component = (props: {}) => {
  const $state = useProxyState({ count: 0, text: 'hello' });

  return (
    <div>
      <div>{$state.text}</div>
      <div>{$state.count}</div>
      <button
        onClick={() => {
          $state.count++;
        }}
      >
        increment
      </button>
    </div>
  );
};

export default Component;
```

### use inside components with computed states

```jsx
import React from 'react';
import { useProxyState } from '@peaca/proxy-state';

const Component = (props: {}) => {
  const $state = useProxyState({ cny: 0, text: 'hello' }, { usd: ($state) => $state.cny * 6.5 });

  return (
    <div>
      <div>{$state.text}</div>
      <div>cny: {$state.cny}</div>
      <div>usd: {$state.usd}</div>
      <button
        onClick={() => {
          $state.cny++;
        }}
      >
        increment
      </button>
    </div>
  );
};
```

### use inside components with computed states and setters

```jsx
import React from 'react';
import { useProxyState } from '@peaca/proxy-state';

const exchangeRate = 6.5;

const Component = (props: {}) => {
  const $state = useProxyState(
    { cny: 0, text: 'hello' },
    { usd: ($state) => $state.cny / exchangeRate },
    {
      usd: ($state, value) => {
        $state.cny += (value - $state.usd) * exchangeRate;
      },
    }
  );

  return (
    <div>
      <div>{$state.text}</div>
      <div>cny: {$state.cny}</div>
      <div>usd: {$state.usd}</div>
      <button
        onClick={() => {
          $state.cny++;
        }}
      >
        increment cny
      </button>
      <button
        onClick={() => {
          $state.usd++;
        }}
      >
        increment usd
      </button>
    </div>
  );
};
```

## use across components

### share state across components, simply move state creation outside of components

```jsx
import React from 'react';
import { createProxyState, useProxyState } from '@peaca/proxy-state';

const $globalState = createProxyState({ count: 0, text: 'hello' })

const ComponentA = (props: {}) => {
  const $state = useProxyState($globalState);

  return (
    <div>
      <div>{$state.text}</div>
      <div>{$state.count}</div>
      <button
        onClick={() => {
          $state.count++;
        }}
      >
        increment
      </button>
    </div>
  );
};

const ComponentB = (props: {}) => {
  const $state = useProxyState($globalState);

  return (
    <div>
      <div>{$state.text}</div>
      <div>{$state.count}</div>
      <button
        onClick={() => {
          $state.count++;
        }}
      >
        increment
      </button>
    </div>
  );
};

const Component = (props: {}) => {
  return (
    <div>
      <ComponentA />
      <hr />
      <ComponentB />
    </div>
  );
};
```

### proxy-state will only rerender components when parts of state you accessed has changed

```jsx
import React from 'react';
import { createProxyState, useProxyState } from '@peaca/proxy-state';

const $globalState = createProxyState({ count: 0, text: 'hello' });

const ComponentA = (props: {}) => {
  const $state = useProxyState($globalState);

  console.log('render A');

  return (
    <div>
      <div>{$state.count}</div>
      <button
        onClick={() => {
          $state.text = Math.random()
            .toString(36)
            .replace(/[^a-z]+/g, '')
            .substr(0, 5);
        }}
      >
        random text
      </button>
    </div>
  );
};

const ComponentB = (props: {}) => {
  const $state = useProxyState($globalState);

  console.log('render B');

  return (
    <div>
      <div>{$state.text}</div>
      <button
        onClick={() => {
          $state.count = Math.floor(Math.random() * 10);
        }}
      >
        random count
      </button>
    </div>
  );
};

const Component = (props: {}) => {
  return (
    <div>
      <ComponentA />
      <hr />
      <ComponentB />
    </div>
  );
};
```

### set state anywhere

```jsx
import React, { useEffect } from 'react';
import { createProxyState, useProxyState } from '@peaca/proxy-state';

const $globalState = createProxyState({ count: 0, text: 'hello' });

setInterval(() => {
  $globalState.count++;
}, 1000);

const ComponentA = (props: {}) => {
  const $state = useProxyState($globalState);

  console.log('---render A');

  return (
    <div>
      <div>{$state.text}</div>
    </div>
  );
};

const ComponentB = (props: {}) => {
  const $state = useProxyState($globalState);

  console.log('---render B');

  return (
    <div>
      <div>{$state.count}</div>
    </div>
  );
};

const Component = (props: {}) => {
  useEffect(() => {
    document.addEventListener('click', () => {
      $globalState.text = Math.random()
        .toString(36)
        .replace(/[^a-z]+/g, '')
        .substr(0, 5);
    });
  }, []);

  return (
    <div>
      <ComponentA />
      <hr />
      <ComponentB />
    </div>
  );
};
```