Giter Site home page Giter Site logo

beekai-oss / little-state-machine Goto Github PK

View Code? Open in Web Editor NEW
1.4K 13.0 53.0 2.96 MB

📠 React custom hook for persist state management

Home Page: https://lrz5wloklm.csb.app/

License: MIT License

JavaScript 5.83% TypeScript 94.17%
react state flux state-management state-machine react-hooks

little-state-machine's People

Contributors

aditya-armal avatar almusweb avatar bluebill1049 avatar ciganandrea avatar d1plo1d avatar dependabot[bot] avatar devonotbevo avatar dipiash avatar erickbelfy avatar flomocommon avatar garth-athena avatar jeffemery avatar jorisre avatar kotarella1110 avatar lookrain avatar mattl75 avatar monkeywithacupcake avatar neighborhood999 avatar snax4a avatar sshquack avatar ssuvorov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

little-state-machine's Issues

npm ERR! code ERESOLVE

Hello I'm receiving an error when trying to install. Any help would be appreciated. Thank you

0 verbose cli [
0 verbose cli   'C:\\Program Files\\nodejs\\node.exe',
0 verbose cli   'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
0 verbose cli   'i',
0 verbose cli   'little-state-machine'
0 verbose cli ]
1 info using [email protected]
2 info using [email protected]
3 timing npm:load:whichnode Completed in 0ms
4 timing config:load:defaults Completed in 1ms
5 timing config:load:file:C:\Program Files\nodejs\node_modules\npm\npmrc Completed in 2ms
6 timing config:load:builtin Completed in 2ms
7 timing config:load:cli Completed in 2ms
8 timing config:load:env Completed in 0ms
9 timing config:load:file:C:\Users\aaron\code\react\consumer-app\.npmrc Completed in 1ms
10 timing config:load:project Completed in 3ms
11 timing config:load:file:C:\Users\aaron\.npmrc Completed in 0ms
12 timing config:load:user Completed in 0ms
13 timing config:load:file:C:\Users\aaron\AppData\Roaming\npm\etc\npmrc Completed in 0ms
14 timing config:load:global Completed in 0ms
15 timing config:load:validate Completed in 0ms
16 timing config:load:credentials Completed in 1ms
17 timing config:load:setEnvs Completed in 1ms
18 timing config:load Completed in 10ms
19 timing npm:load:configload Completed in 11ms
20 timing npm:load:setTitle Completed in 1ms
21 timing config:load:flatten Completed in 2ms
22 timing npm:load:display Completed in 3ms
23 verbose logfile C:\Users\aaron\AppData\Local\npm-cache\_logs\2022-04-26T22_15_14_575Z-debug-0.log
24 timing npm:load:logFile Completed in 9ms
25 timing npm:load:timers Completed in 0ms
26 timing npm:load:configScope Completed in 0ms
27 timing npm:load Completed in 24ms
28 timing arborist:ctor Completed in 0ms
29 silly logfile start cleaning logs, removing 2 files
30 timing idealTree:init Completed in 677ms
31 timing idealTree:userRequests Completed in 4ms
32 silly idealTree buildDeps
33 silly fetch manifest little-state-machine@*
34 timing arborist:ctor Completed in 0ms
35 http fetch GET 200 https://registry.npmjs.org/little-state-machine 863ms (cache revalidated)
36 silly fetch manifest react@^18.0.0
37 http fetch GET 200 https://registry.npmjs.org/react 53ms (cache revalidated)
38 silly fetch manifest react@^16.8.0 || ^17
39 timing idealTree Completed in 1619ms
40 timing command:i Completed in 1631ms
41 verbose stack Error: unable to resolve dependency tree
41 verbose stack     at Arborist.[failPeerConflict] (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\build-ideal-tree.js:1362:25)
41 verbose stack     at Arborist.[loadPeerSet] (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\build-ideal-tree.js:1328:34)
41 verbose stack     at async Arborist.[buildDepStep] (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\build-ideal-tree.js:935:11)
41 verbose stack     at async Arborist.buildIdealTree (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\build-ideal-tree.js:216:7)
41 verbose stack     at async Promise.all (index 1)
41 verbose stack     at async Arborist.reify (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:149:5)
41 verbose stack     at async Install.exec (C:\Program Files\nodejs\node_modules\npm\lib\commands\install.js:157:5)
41 verbose stack     at async module.exports (C:\Program Files\nodejs\node_modules\npm\lib\cli.js:66:5)
42 verbose cwd C:\Users\aaron\code\react\consumer-app
43 verbose Windows_NT 10.0.22000
44 verbose argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "i" "little-state-machine"
45 verbose node v16.14.0
46 verbose npm  v8.3.1
47 error code ERESOLVE
48 error ERESOLVE unable to resolve dependency tree
49 error
50 error While resolving: �[1mrm�[22m@�[1m0.1.0�[22m
50 error Found: �[1mreact�[22m@�[1m18.1.0�[22m�[2m�[22m
50 error �[2mnode_modules/react�[22m
50 error   �[1mreact�[22m@"�[1m^18.0.0�[22m" from the root project
50 error
50 error Could not resolve dependency:
50 error �[35mpeer�[39m �[1mreact�[22m@"�[1m^16.8.0 || ^17�[22m" from �[1mlittle-state-machine�[22m@�[1m4.2.4�[22m�[2m�[22m
50 error �[2mnode_modules/little-state-machine�[22m
50 error   �[1mlittle-state-machine�[22m@"�[1m*�[22m" from the root project
50 error
50 error Fix the upstream dependency conflict, or retry
50 error this command with --force, or --legacy-peer-deps
50 error to accept an incorrect (and potentially broken) dependency resolution.
50 error
50 error See C:\Users\aaron\AppData\Local\npm-cache\eresolve-report.txt for a full report.
51 verbose exit 1
52 timing npm Completed in 1903ms
53 verbose unfinished npm timer reify 1651011314836
54 verbose unfinished npm timer reify:loadTrees 1651011314846
55 verbose unfinished npm timer idealTree:buildDeps 1651011315528
56 verbose unfinished npm timer idealTree:#root 1651011315529
57 verbose code 1
58 error A complete log of this run can be found in:
58 error     C:\Users\aaron\AppData\Local\npm-cache\_logs\2022-04-26T22_15_14_575Z-debug-0.log
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR!   react@"^18.0.0" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.0 || ^17" from [email protected]
npm ERR! node_modules/little-state-machine
npm ERR!   little-state-machine@"*" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
npm ERR! See C:\Users\aaron\AppData\Local\npm-cache\eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\aaron\AppData\Local\npm-cache\_logs\2022-04-26T22_19_09_423Z-debug-0.log

Way to test the store (E2E/Cypress)

Is there an out of the box solution for testing the store out of the box?

A "common" practice for Redux is to attach the store to window and use it inside Cypress, example:

if (window.Cypress) {
  window.store = store;
}

But in the case of little state machine createStore function doesn't return an instance that I can "hook" onto.

I guess I can check the storage, but that is a lot of work/logic inside a test, I would like to avoid it.

Use with NextJS

Is there a way to hydrate things on the SSR? or should I just delay using components that require state?

Method to work around disabled cookies in browser

Hi! We are trying to make LSM work with disabled cookies in the browser. This disables localStorage and sessionStorage in most browsers. This makes even trying to access window.sessionStorage return an access denied exception.

Our solution is to call setStorageType and save to app memory if sessionStorage is disabled.

// Run this only if sessionStorage is disabled or does not exist
const state = {}  
setStorageType({
  setItem: (key, value) => {
    state[key] = value
  },
  getItem: item => state[item],
})

Now normally this should work, but there appears to be a line in the LSM source that depends on sessionStorage being enabled, making our app crash.

let storageType: Storage = isClient
  ? window.sessionStorage
  : {
      getItem: payload => payload,
      setItem: (payload: string) => payload,
      clear: () => {},
      length: 0,
      key: (payload: number) => payload.toString(),
      removeItem: () => {},
    };

In the code above, window.sessionStorage is called, but this crashes our app if it is not available. Of course, we could (try to) use require with a try-catch instead of imports, but we'd rather avoid that.

Would you guys be open to returning null/undefined/otherwise ignore the error if window.sessionStorage is not allowed?

Thanks!

unable to create mock provider for Jest+React testing Lib

So i am trying to setup up testing for my project and all works well except when i try to create a mock/test provider for our test suite.

(nothing too fancy just Next.js 11 + Jest + RTL)

The main issue is that i want to move away from mocking the return value of useStateMachine in favor of just letting the lib do its job and i test the result of the render.

This is also hindering my ability to test click events since they rely on LSM state changes. (ie hook form controlled by lsm).

So i have working providers for react query, i would assume that they would work the same. i did a test with just creating a React.Context provider and that works just fine.

So the main error i am getting is that createStore({...mockStore}) comes back with

// works just fine with the query provider etc. 
// When i add the provider to wrap other existing providers (ie query client for react-query) it fails

import * as React from 'react';
import { StateMachineProvider, createStore } from 'little-state-machine';
import { initialState } from '../../store/states';
import { QueryClient, QueryClientProvider } from 'react-query';

import { render } from '@testing-library/react';



const createTestQueryClient = () =>
  new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
    },
  });

const mockStore = () =>
  createStore({
    ...initialState
  });

// HOC for rendering our ui components with the query client along with testing configs
export function renderWithClient(ui) {
  mockStore();
  const testQueryClient = createTestQueryClient();

  const { rerender, ...result } = render(
    <StateMachineProvider>
      <QueryClientProvider client={testQueryClient}>{ui}</QueryClientProvider>
    </StateMachineProvider>
  );
  return {
    ...result,
    rerender: (rerenderUi) =>
      rerender(
        <StateMachineProvider>
          <QueryClientProvider client={testQueryClient}>{rerenderUi}</QueryClientProvider>{' '}
        </StateMachineProvider>
      ),
  };
}

// Query Client Context wrapper for our tests, use this separately when we want to
// use it to render hooks outiside components for testing
export function createWrapper() {
  const testQueryClient = createTestQueryClient();
  mockStore();

  return ({ children }) => (
    <StateMachineProvider>
      <QueryClientProvider client={testQueryClient}>{children}</QueryClientProvider>;
    </StateMachineProvider>
  );
}
}

i get the below error, which basically tells me that little state machine is undefined, and checking console confirms same.

 TypeError: (0 , _littleStateMachine.createStore) is not a function

      27 |
      28 | const mockStore = () =>
    > 29 |   createStore({
         |   ^
      30 |     user,
      31 |     points,
      32 |     transactions,

      at mockStore (__mocks__/utils/index.js:29:3)
      at renderWithClient (__mocks__/utils/index.js:44:3)

This is how i would normally create all my mockProviders (for which all except LSM are 100% working)

Any ideas/thoughts? Has anyone created test suites with LSM provider?

Middle-wares could have access to more than just the state

Current

Middle-wares receive the state just updated by the action.

Idea

Middle-wares could also receive:

  1. The action name
  2. The payload that was provided to the action

Example

With state, action name and payload, a middleware could do something like this:

function middleware(state, actionName, payload) {
  if (actionName === 'specialAction') return state;

  sendLogSomewhere(payload);

  return {
    ...state,
    ...performMagic(state)
  }
}

[Question] use with externalStore and get new state immediatley

I'm building a react-hook-form wizard and am trying to use the syncStores function.
When submitting a form to go to the next page, the entire state disappears, even if I'm just returning the existing sessionStorage.
Am I doing it right?

https://codesandbox.io/s/github/svict4/RHF-LSM-with-RR

It's probably because I don't know how to use the library properly, does anyone have a more concrete example of POSTing or GETing data from an endpoint for the transform function?

function log(store: any) {
  console.log('this function logs the store:', store);
}

function PostData(store: any) {
  console.log('this function will trigger an API call to post data'); // is this the best place to put it?
}

window.sessionStorage.setItem(
  'formData',
  '{"yourDetails": {"firstname": "bull", "lastname": "le", "addresses": [{"street": "street"}]}}',
);

const mergeStore = (sessionData: any, data: any) => merge(data, sessionData);

// where externalStoreData is provided from an API
const externalStoreData = {
  yourDetails: { firstname: 'sdfsdf', middlename: 'dfsdfsdf' },
};

createStore(
  {
    yourDetails,
  },
  {
    name: 'formData',
    middleWares: [log, PostData],
    syncStores: {
      externalStoreName: 'API',
      transform: ({ externalStoreData, currentStoreData }) => {
        // just returning the current store doesn't seem to work after submit?
        return JSON.parse(window.sessionStorage.formData);
      },
    },
  },
);

Also, after setting the data in an action, I'd like to get state of the new store, so that I can pass it to my react-router function and do some logic. But state contains the previous state before updating, what's a better way of getting the new state?

  const onSubit = data => {
    action(data);
    console.log(state); // I want to access the NEW state after the update
    props.history.push('./result'); // so I can use it here
  };

Specify the type of state on hook

Make possible to create multiple stateMachines without creating GlobalState type, just infer it from updateAction first argument, or pass as generic to useStateMachine

Enable React-Native support

When trying to use your awesome state machine in my React native app i get the error:

Can't find variable: document.

I assume this is the DEV tools causing this problem. Any clues you can give me or timeline for implementation would be awesome

Thanks

using multiple actions

Hey dumb question as I seemingly can't read the type properly

if I set up multiple actions like so:

const { state, actions } = useStateMachine(
    { saveAction, sorryAction },
    { saveAction: "saveToDB", sorryAction: "sorry" }
);

how do I send an update to only one of the actions? it's not this:

actions([{ key: "sorry" }], {
    reason: "you dun goofed"
});

window.STATE_MACHINE_RESET is not a function

Hey Bill & team. Attempting to use the RESET GUI button from LSM renders the following error:

image

Forces a reload, with the state persisting.

"little-state-machine": "^4.0.0",
"little-state-machine-devtools": "^1.0.0",

Possibility to separate state to prevent rerendering?

I guess this is more a question or feature request: I would like to "subscribe" only to a part of the state to prevent unnecessary rerenders. For example ComponentA may only use fieldA of my global state. But currently if fieldB is changed also ComponentA is rerendered. Is there already any possibility to prevent this or could this be a future feature?

See this csb and watch the console for rerendering of the components.

Way to use this with multiple stores and type safety

Is there any way to create multiple stores while ensuring state type safety?

As far as I see you need to define a global definition file that corresponds to globalstate but i want to have several small stores instead.

PS: Thanks for creating this

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this 💪.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two Factor Authentication for your account, set its level to "Authorization only" in your account settings. semantic-release cannot publish with the default "
Authorization and writes" level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot 📦🚀

Middlewares all call same data object - would like it to act as a pipe.

Problem

I expected the middlewares to behave like a pipe like with other libraries. Documentation didn't specify that, but I think it's typically more intuitive than the current implementation. Currently:

const storeData = getStore();
if (Array.isArray(middleWaresArray) && middleWaresArray.length) {
  middleWaresArray.forEach((callback) => {
    callback(storeData);
  });
}
updateStore(storeData);

Proposal

const storeData = getStore();
let pipeData;
if (Array.isArray(middleWaresArray) && middleWaresArray.length) {
  pipeData = middleWaresArray.reduce((currentValue, currentFunction) => {
    return currentFunction(currentValue);
  }, storeData);
}
updateStore(pipeData);

Read state onSubmit

I expect that after action(data) the state would be updated. But it remains the previous state. How do I access the updated state?

const onSubmit = (data) => {
    action(data)
    console.log('data:', data) // partial store
    console.log('state:', state) // previous state
  }

This is invoked using RHF:
<form onSubmit={handleSubmit(onSubmit)}>

Unexpected Reset Behavior

This might be a misunderstanding on my part, but this at least seems unexpected. I can't seem to get a working example where I reset the state of the form to where it started without refreshing the page manually.

I tried both calling the window.STATE_MACHINE_RESET and creating a reset function that sets the state back to what the app started with. Neither of these seem to trigger the app to reload. Additionally, the DevTool reset button doesn't seem to actually reset the data in the DevTool without refreshing the window, which seems a bit odd to have a button that doesn't show any feedback.

Here is my modified demo app with the reset function. I added a reset button that triggers the reset function, which just sets the state back to the original.

Steps I'm taking in my demo app:

  • Show console
  • Change "bill" to "tom"
  • Click Submit (see console where data has been updated)
  • Click Reset (see console where data has been updated)
  • Observe the first field still says "tom"

Also:

  • Show DevTool
  • Change "bill" to "tom"
  • Click "Reset" in the DevTool
  • Observe no change in the data
  • Click the refresh button for the app window
  • Observe first input now says "bill"

Using with node

Hey, Thanks for the great package. I am trying to use this with Next.js but I get the following error when SSR is happening. Would you consider adding support for isomorphic apps in the future.

ReferenceError: window is not defined
createStore
./node_modules/little-state-machine/dist/index.js:164:9

Typescript custom GlobalState type is not detected

Issue

Following the example at https://github.com/bluebill1049/little-state-machine#%EF%B8%8F-type-safety-ts does not override the GlobalState

Steps to repro:

  1. Created custom typings file in custom-types/global.d.ts
  2. Added custom typings file to the tsconfig.json using typedRoots: ['./custom-typings']
  3. Added the GlobalState declaration
import 'little-state-machine';

declare module 'little-state-machine' {
  interface GlobalState {
    yourDetail: {
      name: string;
    };
  }
}
  1. Typescript throws on action handler definition:
Property 'yourDetail' does not exist on type 'GlobalState'.  TS2339

     8 |   ...state,
     9 |   yourDetail: {
  > 10 |     ...state.yourDetail,
       |              ^
    11 |     ...payload,
    12 |   },
    13 | });

Codesandbox

Please see issue at https://codesandbox.io/s/sad-lamarr-ko811?file=/src/App.tsx

Actions always trigger useEffect when in dependencies

I have useEffects in my codebase that have little-state-machine actions as dependencies, everything worked fine until I update little-state-machine from version "3.1.2" to 4.1.0. Now Actions call every time useEffect and re-render my components.
Also tried with TS demo sample from your docs, only added this effect :
useEffect(() => { console.log("called every time"); actions.updateFirstLastName({ yourDetails: { firstname: "testFirst", lastname: "testLast" } }); }, [actions]);
in Form.tsx file. And got same result.

Not sure what to do, can someone help?

Can't use it on react native

I've been trying to setStorageType(AsyncStorage) in react native but it does not work. I've checked the index and it seems setStorageType isn't provided. Is there support for react native at the moment?

How to push data to an array state machine

My idea is to push data to an array with the same form. So everytime i press send, it appends it to the array.

Here is my following state:

createStore({
	data: {
		id: '1',
		role: '',
		name: '',
		mail: '',
		addictions: [],
		phisiology_logs: [],
		achievements: [],
	},
});

And this is my form (using react-hook-form)

const onSubmit = (data) => {
	console.log('state es, ', state.data.counter);

	actions.updateAction(data);
	console.log('data', data);
};

return (
	<div className="">
			<form action="" onSubmit={handleSubmit(onSubmit)}>
				<div className="flex items-start space-x-4 pb-">
					<div className="flex-shrink-0"></div>
					<div className="flex-1 min-w-0">
						<div className="overflow-hidden border border-gray-300 rounded-lg shadow-sm focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500">
							<label htmlFor="comment" className="sr-only">
								Agrega tu comentario
							</label>
							<textarea
								rows={3}
								name=""
								className="block w-full py-3 border-0 resize-none focus:ring-0 sm:text-sm"
								placeholder="Add your comment..."
								defaultValue={''}
								{...register(
									`phisiology_logs[0].description`,
									{
										required: 'Required',
									}
								)}
							/>
						</div>
						<select
							{...register(
								`phisiology_logs[0].feel`,
								{
									required: true,
								}
							)}
							className="block px-2 py-2 border border-gray-200 rounded-lg shadow-sm focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500"
						>
							<option value="5">😁 Feliz</option>
							<option value="4">😀 Bien</option>
							<option value="3">😐 Neutro</option>
							<option value="2 ">😥 Triste </option>
							<option value="1">😭Muy Mal</option>
						</select>
						<input
							type="date"
							className="hidden"
							defaultValue={
								new Date().toISOString().split('T')[0]
							}
							placeholder="date"
							{...register(
								`phisiology_logs[0].date`,
								{
									required: true,
								}
							)}
						/>
						<button
							type="submit"
							className="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
						>
							Send
						</button>
					</div>
				</div>
			</form>
	</div>
);

You can see im just adding this information to the index 0 of the phisiology_logs array. How can i append or push data to the state (data.phisiology_logs[]) object? So everytime i press 'Send' it pushes data to the array.

Disabling cookies in Chrome causes window.sessionStorage lookup to error

It looks like the sessionStorage lookup needs to be wrapped in a try catch to allow for Chrome users with cookies disabled:

src.f69400ca.js:116 Uncaught DOMException: Failed to read the 'sessionStorage' property from 'Window': Access is denied for this document.
    at new e (http://localhost:1234/src.f69400ca.js:11651:87)
    at Object.parcelRequire.../node_modules/little-state-machine/dist/little-state-machine.es.js.react (http://localhost:1234/src.f69400ca.js:11649:9)
    at newRequire (http://localhost:1234/src.f69400ca.js:47:24)
    at localRequire (http://localhost:1234/src.f69400ca.js:53:14)
    at Object.parcelRequire.index.tsx.core-js/modules/es6.array.copy-within (http://localhost:1234/src.f69400ca.js:108133:30)
    at newRequire (http://localhost:1234/src.f69400ca.js:47:24)
    at http://localhost:1234/src.f69400ca.js:81:7
    at http://localhost:1234/src.f69400ca.js:120:3
    ```

how to use persist state in react-native

import AsyncStorage from '@react-native-community/async-storage'
import {StateMachineProvider, createStore, setStorageType} from 'little-state-machine'

setStorageType(AsyncStorage)
createStore(InitStore, {name: 'xxx'})

const App = () => {
return (

...

)
}

is this correct?
when i shake & reload the app, the store's gone

How to implement array of objects.

I have a list of questions with answer option yes and no. If I click on Yes , then it's value should add on store and when I click on No option, then it's value should remove from store. I want to manage by array.

Storage option

What about adding a configuration option to choose between localStorage & sessionStorage?

Global State Management or Local State Management

I read the docs but I didn't understand if I can manage a global state dispatching actions like Redux.

With this lib can I control Global State, access it and dispatch actions on any component or is just for local state management?

Error on SSR projects with actions execution

Now I see that source code in tag v3.0.2 (https://github.com/bluebill1049/little-state-machine/releases/tag/v3.0.2), doesn't contain changes for middleware.

In archive:

export const middleWare = (data: string = '') => {
  if (data) {
    // @ts-ignore
    window[STORE_ACTION_NAME] = data;
  }
  return data;
};
...
 if (isDevMode) {
    middleWare(debugName);
  }

...

and when I execute action on Server Side I have an error:

ReferenceError: window is not defined
    at middleWare (/ssr/node_modules/little-state-machine/dist/little-state-machine.js:125:9)
    at Object.updateUserData (/ssr/node_modules/little-state-machine/dist/little-state-machine.js:163:9)

crashes, when adding dev tool

So as soon as i import the dev tool, app crashed with the below message. (state machine works just fine)
I am using a Next.js app, any toughts or suggestions would really help :)

\little-state-machine-devtools\dist\index.js:1
import * as React from 'react';
^^^^^^

SyntaxError: Cannot use import statement outside a module

the problem is with the import statement itself for some reason

import { DevTool } from 'little-state-machine-devtools';

Help with the LocalStorage and Next.JS

Hey Guys, i am using the little-state-machine to store some data, but the default of the library is to use sessionStorage.

I am trying to change to localStorage but without success, returns error:

e.setItem is not a function

import React from "react";
// Sheets
import "../styles/globals.css";
import "../styles/globals-mobile.css";
import "../styles/bootstrap.min.css";
import { SnackbarProvider } from "notistack";
import { StateMachineProvider, createStore, setStorageType } from "little-state-machine";

createStore(
  {
    user: null,
    oferta: {},
    mensagensAgendadas: [],
    metricas: {},
  },
  {
    storageType: window.localStorage
  }
);

function MyApp({ Component, pageProps }) {
  return (
    <>
      <StateMachineProvider>
        <SnackbarProvider maxSnack={3}>
          <Component
            {...{
              ...pageProps,
            }}
          />
        </SnackbarProvider>
      </StateMachineProvider>
    </>
  );
}

export default MyApp;

NextJS: Warning: Text content did not match. Server: "..." Client: "..."

Hi there

How do I resolve this issue in NextJS with LSM?

Example in NJ:

import { StateMachineProvider, createStore, useStateMachine } from 'little-state-machine';

createStore({
  yourDetail: { name: 'Bruce' },
});

function updateName(state, payload) {
  return {
    ...state,
    yourDetail: {
      ...state.yourDetail,
      ...payload,
    },
  };
}

function YourComponent() {

  const { actions, state } = useStateMachine({ updateName });

  return (
    <div onClick={() => actions.updateName({ name: 'bill' })}>
      {state.yourDetail.name}
    </div>
  );
}


function MyApp({ Component, pageProps }) {
  return (
    <StateMachineProvider>
      <YourComponent {...pageProps} />
    </StateMachineProvider>
  )
}

export default MyApp

unable to clear store

I am using lsm with react-router for a wizard on a client's site and I need to reset the store when a user returns to the wizard landing page. I found this solution in stack overflow (https://stackoverflow.com/questions/64822032/react-little-state-machine-clear-data) but I cant get it to work. I cant show the full application, but from the below can you see anything wrong with what I have done.

Using

    "react-router-dom": "^6.2.1",
    "little-state-machine": "^4.2.0",
    "little-state-machine-devtools": "^2.0.1",

App.js

createStore({
  data
});

function App() {
  
    return (
      <StateMachineProvider>
        <DevTool />
        <div className="container">
          ...
          <Router>
            <Steps />
          </Router>
        </div>
      </StateMachineProvider>
    );
  }

  export default App;
  

Steps.js

....
import { useStateMachine } from "little-state-machine";
import clearAction from "./lsm/actions/clearAction";
...

export default () => {
    ....
   const location = useLocation();
   const { state, actions } = useStateMachine({ clearAction });
   ...
   
   useEffect(() => {
   
       let step = location.pathname.split("/")[2];
       // landing page location = http://site.co.uk/wizard
       // steps have url = http://site.co.uk/wizard/step[1-4]
       if(!step){
     
           actions.clearAction();
   
       }

   }, []);

return (...);
};

clearAction.js

export default function clearAction(state, payload) {
   return {};
 }

I even tried to use window.LSM_RESET(), sessionStorage.removeItem('LSM') and sessionStorage.clear(). None of these work.

Is there a simpler way to reset/clear the store from within a component?

Way to turn off storage by default

I was using little-state-machine with react-hook-form and had some conditional state that I didn't want lsm to remember on load.

The only way I found to implement this was something like this:

const initialState = {/* whatever you want */}
createStore(
  { ...initialState },
  {
    middleWares: [],
    syncStores: {
      // you can sync with external store and transform the data
      externalStoreName: 'initial',
      transform: ({ externalStoreData, currentStoreData }) => {
        return {
          ...initialState,
         // here add any other state from external or current
        };
      }
    }
  }
);

I actually really like this package a lot and would be happy submitting a PR for what I'm thinking, unless I'm not on the right track.

AsyncStorage doesn't work with react-native

I don't see how this should currently work, since AsyncStorage is async.... ?

At least I don't know how to make it work in my App. It doesn't restore / or save the data.

Any hints would be helpful. Thank you ❤️

import React from 'react';
import AsyncStorage from '@react-native-community/async-storage';
import {
  StateMachineProvider,
  createStore,
  setStorageType,
} from 'little-state-machine';

import App from './App';

setStorageType(AsyncStorage);

const data: LittleState = {
  xFormData: {},
};

createStore(data);

const AppContainer = () => (
    <StateMachineProvider>
        <App />
    </StateMachineProvider>
);

export default AppContainer;

Exported type for action expects store.

The type that is exported from useStateMachine is Action

export function useStateMachine<T extends Store = Store>(
  updateStoreFunction?: UpdateStore,
  options?: Options,
): {
  action: Action;
  actions: Actions;
  state: T;
} {

which reflects this type:

export declare type Action = (store: any, payload: any) => any;
export declare type Actions = {
    [key: string]: Action;
};

which means that when you use the function action or functions from the actions object, it expects both parameters.

Proposal

change return types to UpdateStoreFunction:

export declare type UpdateStoreFunction = <T>(payload: T) => T;

in order to reflect usage per documentation.

Code Sample in TS is not working correctly

When cloning the code sample from Code Sanbox (wild-dawn-ud8bq) you have to submit the form twice for the state to update?

Using:
import { GlobalState } from 'little-state-machine'; export function updateFirstLastName( state: GlobalState, payload: { firstname: string; lastname: string; } ) { console.log('state before:', state); console.log('payload:', payload); return { ...state, yourDetails: { ...payload, }, }; }

and

const onSubmit = (data: FormValues) => { actions.updateFirstLastName(data); console.log('state after:', state); };

this shows when changing any field it requires submission twice even when the payload is correct. I hope this is correct how I have gone about this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.