GithubHelp home page GithubHelp logo

dai-shi / reactive-react-redux Goto Github PK

View Code? Open in Web Editor NEW
502.0 12.0 12.0 7.08 MB

[NOT MAINTAINED] React Redux binding with React Hooks and Proxy

Home Page: https://www.npmjs.com/package/reactive-react-redux

License: MIT License

JavaScript 10.05% TypeScript 89.95%
reactjs redux react-redux react-hooks hooks-api reactive proxy react

reactive-react-redux's Introduction

This project is no longer maintained. react-tracked works with react-redux and covers the use case of reactive-react-redux. Redux docs officially recommends proxy-memoize as a selector library, and it provides similar developer experience to that of reactive-react-redux. Both are good options.


There are several projects related to this repo. Here's the index of those.

  • reactive-react-redux v5-alpha (this repo): This has an experimental react-redux binding with useMutableSource. It provides useTrackedState, which tracks the usage of state in render, and it's originally proposed in this repo.
  • react-tracked: This project is to provide useTrackedState with React Context. v1.6 provides createTrackedSelector that will create useTrackedState from useSelector.
  • react-redux #1503: A pull request to add useTrackedState to the official react-redux library.
  • proxy-memoize: This is another project which is not tied to React, but combined with useSelector, we get a similar functionality like useTrackedState.

reactive-react-redux

CI npm size discord

React Redux binding with React Hooks and Proxy

If you are looking for a non-Redux library, please visit react-tracked which has the same hooks API.

Introduction

This is a library to bind React and Redux with Hooks API. It has mostly the same API as the official react-redux Hooks API, so it can be used as a drop-in replacement if you are using only basic functionality.

There are two major features in this library that are not in the official react-redux.

1. useTrackedState hook

This library provides another hook useTrackedState which is a simpler API than already simple useSelector. It returns an entire state, but the library takes care of optimization of re-renders. Most likely, useTrackedState performs better than useSelector without perfectly tuned selectors.

Technically, useTrackedState has no stale props issue.

2. useMutableSource without Context

react-redux v7 has APIs around Context. This library is implemented with useMutableSource, and it patches the Redux store. APIs are provided without Context. It's up to developers to use Context based on them. Check out ./examples/11_todolist/src/context.ts.

There's another difference from react-redux v7. This library directly use useMutableSource, and requires useCallback for the selector in useSelector. equalityFn is not supported.

How tracking works

A hook useTrackedState returns an entire Redux state object with Proxy, and it keeps track of which properties of the object are used in render. When the state is updated, this hook checks whether used properties are changed. Only if it detects changes in the state, it triggers a component to re-render.

Install

npm install reactive-react-redux

Usage (useTrackedState)

import React from 'react';
import { createStore } from 'redux';
import {
  patchStore,
  useTrackedState,
} from 'reactive-react-redux';

const initialState = {
  count: 0,
  text: 'hello',
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'increment': return { ...state, count: state.count + 1 };
    case 'decrement': return { ...state, count: state.count - 1 };
    case 'setText': return { ...state, text: action.text };
    default: return state;
  }
};

const store = patchStore(createStore(reducer));

const Counter = () => {
  const state = useTrackedState(store);
  const { dispatch } = store;
  return (
    <div>
      {Math.random()}
      <div>
        <span>Count: {state.count}</span>
        <button type="button" onClick={() => dispatch({ type: 'increment' })}>+1</button>
        <button type="button" onClick={() => dispatch({ type: 'decrement' })}>-1</button>
      </div>
    </div>
  );
};

const TextBox = () => {
  const state = useTrackedState(store);
  const { dispatch } = store;
  return (
    <div>
      {Math.random()}
      <div>
        <span>Text: {state.text}</span>
        <input value={state.text} onChange={event => dispatch({ type: 'setText', text: event.target.value })} />
      </div>
    </div>
  );
};

const App = () => (
  <>
    <h1>Counter</h1>
    <Counter />
    <Counter />
    <h1>TextBox</h1>
    <TextBox />
    <TextBox />
  </>
);

API

patchStore

patch Redux store for React

Parameters

  • store Store<State, Action>

Examples

import { createStore } from 'redux';
import { patchStore } from 'reactive-react-redux';

const reducer = ...;
const store = patchStore(createStore(reducer));

useTrackedState

useTrackedState hook

It return the Redux state wrapped by Proxy, and the state prperty access is tracked. It will only re-render if accessed properties are changed.

Parameters

  • patchedStore PatchedStore<State, Action>
  • opts Opts (optional, default {})

Examples

import { useTrackedState } from 'reactive-react-redux';

const Component = () => {
  const state = useTrackedState(store);
  ...
};

useSelector

useSelector hook

selector has to be stable. Either define it outside render or use useCallback if selector uses props.

Parameters

  • patchedStore PatchedStore<State, Action>
  • selector function (state: State): Selected

Examples

import { useCallback } from 'react';
import { useSelector } from 'reactive-react-redux';

const Component = ({ count }) => {
  const isBigger = useSelector(store, useCallack(state => state.count > count, [count]));
  ...
};

memo

memo

Using React.memo with tracked state is not compatible, because React.memo stops state access, thus no tracking occurs. This is a special memo to be used instead of React.memo with tracking support.

Parameters

  • Component any
  • areEqual any?

Examples

import { memo } from 'reactive-react-redux';

const ChildComponent = memo(({ obj1, obj2 }) => {
  // ...
});

Recipes

Context

You can create Context based APIs like react-redux v7.

import { createContext, createElement, useContext } from 'react';
import {
  PatchedStore,
  useSelector as useSelectorOrig,
  useTrackedState as useTrackedStateOrig,
} from 'reactive-react-redux';

export type State = ...;

export type Action = ...;

const Context = createContext(new Proxy({}, {
  get() { throw new Error('use Provider'); },
}) as PatchedStore<State, Action>);

export const Provider: React.FC<{ store: PatchedStore<State, Action> }> = ({
  store,
  children,
}) => createElement(Context.Provider, { value: store }, children);

export const useDispatch = () => useContext(Context).dispatch;

export const useSelector = <Selected>(
  selector: (state: State) => Selected,
) => useSelectorOrig(useContext(Context), selector);

export const useTrackedState = () => useTrackedStateOrig(useContext(Context));

useTrackedSelector

You can create a selector hook with tracking support.

import { useTrackedState } from 'reactive-react-redux';

export const useTrackedSelector = (patchedStore, selector) => selector(useTrackedState(patchedStore));

Please refer this issue for more information.

useTracked

You can combine useTrackedState and useDispatch to make a hook that returns a tuple like useReducer.

import { useTrackedState, useDispatch } from 'reactive-react-redux';

export const useTracked = (patchedStore) => {
  const state = useTrackedState(patchedStore);
  const dispatch = useDispatch(patchedStore);
  return useMemo(() => [state, dispatch], [state, dispatch]);
};

Caveats

Proxy and state usage tracking may not work 100% as expected. There are some limitations and workarounds.

Proxied states are referentially equal only in per-hook basis

const state1 = useTrackedState(patchedStore);
const state2 = useTrackedState(patchedStore);
// state1 and state2 is not referentially equal
// even if the underlying redux state is referentially equal.

You should use useTrackedState only once in a component.

An object referential change doesn't trigger re-render if an property of the object is accessed in previous render

const state = useTrackedState(patchedStore);
const { foo } = state;
return <Child key={foo.id} foo={foo} />;

const Child = React.memo(({ foo }) => {
  // ...
};
// if foo doesn't change, Child won't render, so foo.id is only marked as used.
// it won't trigger Child to re-render even if foo is changed.

You need to use a special memo provided by this library.

import { memo } from 'reactive-react-redux';

const Child = memo(({ foo }) => {
  // ...
};

Proxied state might behave unexpectedly outside render

Proxies are basically transparent, and it should behave like normal objects. However, there can be edge cases where it behaves unexpectedly. For example, if you console.log a proxied value, it will display a proxy wrapping an object. Notice, it will be kept tracking outside render, so any prorerty access will mark as used to trigger re-render on updates.

useTrackedState will unwrap a Proxy before wrapping with a new Proxy, hence, it will work fine in usual use cases. There's only one known pitfall: If you wrap proxied state with your own Proxy outside the control of useTrackedState, it might lead memory leaks, because useTrackedState wouldn't know how to unwrap your own Proxy.

To work around such edge cases, the first option is to use primitive values.

const state = useTrackedState(patchedStore);
const dispatch = useUpdate(patchedStore);
dispatch({ type: 'FOO', value: state.fooObj }); // Instead of using objects,
dispatch({ type: 'FOO', value: state.fooStr }); // Use primitives.

The second option is to use getUntrackedObject.

import { getUntrackedObject } from 'react-tracked';
dispatch({ type: 'FOO', value: getUntrackedObject(state.fooObj) });

You could implement a special dispatch function to do this automatically.

Examples

The examples folder contains working examples. You can run one of them with

PORT=8080 npm run examples:01_minimal

and open http://localhost:8080 in your web browser.

You can also try them in codesandbox.io: 01 02 03 04 05 06 07 08 09 11 12 13

Benchmarks

benchmark result

See #32 for details.

Blogs

reactive-react-redux's People

Contributors

bostondv avatar dai-shi avatar dependabot[bot] 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

reactive-react-redux's Issues

Other discussions around auto-detecting Redux state usage

There's been some other experimentation and discussion around auto-detecting which pieces of Redux state are used. In particular, @theKashey has done a lot of work around trying to use proxies, but apparently there's a number of difficult edge cases.

Please see respond-framework/remixx#1 and reduxjs/react-redux#1018 for related discussion.

If you've got ideas for how we can leverage this kind of functionality in a future version of React-Redux, I'd appreciate any help you can provide!

Component not aware of state change?

I've been fighting this all day today.
Im new to Java/TypeScript world, React world and Redux world and I was pretty sure that I messed something up... until I tried doing the same with React-Redux (7.0.0.beta-1) and it turned out it works there!

Im writing a authorization flow with redux-saga - so this example that Im going to show you is just massively simplified code similar to mine. CodeSandboxes below.

Description: TOGGLE button dispatches an action that is caught by redux-saga. The Saga dispatches an action to toggle a value to true, wait 10ms, and then dispatches another action to toggle value back to false. Meanwhile the button is disabled if value === true, and there is a value ? 'ON' : 'OFF' text. Interestingly if you increase delay() value to (for example) 50ms it works!

How does it look like:

  • using react-redux 7.0.0-beta.1 (good!)
    react-redux

  • using reactive-react-redux 1.8.0 (bad!)
    reactive-react-redux

This was shot on MacOs 10.14.4 and Safari 12.1.
I have tested this also on:

  • iOS: latest Safari, latest Chrome and latest Firefox. Results are the same, although on Firefox sometimes I had to click "toggle button" couple of times to "achieve" this issue.
  • MacOs: latest Chrome, latest Firefox. On Firefox and Chrome sometimes it needs couple of clicks to get there.

Check out these codesandboxes:

I dropped on this issue by accident. In my original code the delay function is just a Api call. This Api call had a wrong port number set so it got Connection refused and returned immediately. TURN_ON and TURN_OFF was just a isLoading indicator that disabled a Login button.

@dai-shi Im totally blown away by Your work on reactive-react-redux and @theKashey 's proxyequal. I follow every discussion, every benchmark test and commits to this repo and wish I would understand enough of it to be able to help...

re: selectors

@dai-shi @theKashey @ScriptedAlchemy

So I've been doing some thinking around selectors, and I've come to the conclusion that the babel plugin approach is a horrible path to hell. I'll describe why in a second. Here's the alternative:

function MyComponent(props) {
   const state = useReduxState(props, someArgEtc) // here's the important line
   return <div>{state.fooSelector(props, someArgEtc)}</div>
}

===

function MyComponent(props) {
   const state = useReduxState()
   return useMemo(<div>{state.fooSelector(props, someArgEtc)}</div>, [props, someArgEtc])
}

So, basically we make the user/developer do a little bit of work by providing the dependencies to track. And we dont make em think about useMemo.


Of course to do this properly, rests on useReduxState knowing about selectors, so therefore Redux must be forked to have this createStore API:

const selectors = {
   fooSelector: (state, props, someArgEtc) => ...,
   anotherSelector: (state, etc) => ...
}
const store = createStore(reducers, selectors) // both are automatically "combined"

Now, we know what selectors we have like reducers. Therefore, the proxy can prevent re-render from within the hook. It does so by shallow comparison of the argument dependencies.

Hell, we could even accomplish this without a fork of redux. useReduxState can accept additional args that are simply compared for changes. And of course it's up to the developer to match with actual usage of selectors.


Why we dont wanna mess with babel?

Here's why:

function RespondComponent(props, state, actions) {
    if (props.foo) return <div>{state.selectorA(props)}</div>
    return <div>{state.selectorB(props)}</div>
}

-->

function RespondComponent(props, state, actions) {
    if (props.foo) {
        const valA = state.selectorA(props)
        return useMemo(<div>{valA}</div>, [valA])
    }

     const valB = state.selectorB(props)
     return useMemo(<div>{valB}</div>, [valB])
}

And that's the easiest possible example!

If making all the appropriate visitations of selectors in search of selectors is even 100% reliable, then taking this to the next level where selectors are correctly conditionally depended upon is even more error-prone.

Also, nobody talks about babel compilation speed, but this stuff adds up. Nobody wants compilation time decreased because of this stuff.

Anyway the reliability factor is just too low based on my experience doing babel plugins.


Now that all said, I think we've found the perfect solution for how to handle this in runtime code within existing proxies! The only caveat is you have to have a store creation mechanism like in Respond Framework. Which isn't really a caveat since that's the exact direction we're going, and since we could also just give useReduxState additional super powers of bail-out capabilities through passing it deps, as if it was useMemo.

Any tips to make this a reality are much appreciated.

Discussion: Antipattern to recommend `useTrackedSelector`

I'm in the process of migrating to this library from react-redux (it's made a very large positive performance impact) -- but I noticed that the recipe for useTrackedSelector contains a useTrackedState() call inside of it.

If a developer who has components with muliple useSelector calls were migrating from react-redux and implemented this recipe, wouldn't they violate the recommendation to only use useTrackedState() once in each component?

Question about re-evaluation strategy

This looks like a very nice library, congratulations!

I was wondering, suppose a component reads a.b.c from tracked state a. Suppose a new state a is reduced, and a.b also "changes", but a.b.c remains the same. I guess in this case the component will not re-render? In other words, to determine if a component should re-render, you
always compare the leaf nodes of the dependency tracking graph?

Is this reasoning correct?

Handling stale props?

facebookarchive/redux-react-hook#39 (comment)

After reading this thread, I'm afraid this library is not handling the stale props, yet.
As far as I understand, the problem is that the props in the render phase is not sync with the previous props in the commit phase which are likely to exist in closures created in useEffect.

I wonder, it can be simply solved by calling a callback in each commit phase, or not?

Testing Environment Slowdown

I'm noticing a huge degradation in my test runner performance after switching to reactive-react-redux. I use jest and create pretty large/deep redux-connected components pretty rapidly.

Is there something that could be affecting the performance here? Should things be torn down in some way?

Try new proxyequal

Hey - I've just pushed some updated to the proxyequal, but did not update the package yet.

I need you first to test it, as only you could do.

Changes:

  • proxyObjectRest, proxyArrayRest (mostly for @ScriptedAlchemy) - they have to be separate commands :(
  • WeakMap memoization for collectValuables possible after adopting more "immutable" approach for tracking changes.
  • I've reproduced your approach for collectValuables, proven to be the fastest, for proxyShallowEqual - it should be faster than proxyEqual from now :)
  • some code was added to handle Object.values issue, which may make things not so performant (but I could try to memoize that moment to mitigate the problem)

All my tests for proxy-equal and libraries derived from it are green. Once you will report ๐Ÿ’š - it will go live.

Why calculateChangedBits = () => 0

Background

React-Redux v6 (RR6) introduced what I'd call the state-based context value.
The idea was to let React propagate re-render instead of triggering re-render from outside of React. This makes it easy to ensure components render top-down the component tree.
Unfortunately, a way to bail out with useContext didn't come, as I understand because there's no way to implement that in an efficient way.
So, React-Redux v7 (RR7) went back to store context and subscriptions.

Problem (Hypothetical)

We are not sure what the final concurrent mode will look like, but @markerikson had a comment in the code.

// TODO We're reading the store directly in render() here. Bad idea?
// This will likely cause Bad Things (TM) to happen in Concurrent Mode.
// Note that we do this because on renders _not_ caused by store updates, we need the latest store state
// to determine what the child props should be.

My understanding is if a component reads a state from the store, it might not be consistent for all components in the tree. If React pauses rendering in the middle of the tree, Redux may update the store state. So, a component A and a component B could get different state even in a single render in the tree. I was hoping batchedUpdates solves this, but unless batchedUpdates run all renders synchronously, Redux has a chance to update the store state.
If we could only read a state from the context like RR6, this problem should be solved.

That doesn't mean all issues around concurrent mode are solved. a warning comment by @gaearon .

Solution

We specify calculateChangedBits = () => 0; so that React doesn't propagate updates.
Only a single Provider subscribes to the Redux store. All components under the Provider subscribe to the Provider. When the store state is updated, Provider re-renders which triggers listeners, subscribed components check updates (in useSelector) and forces render. When a component re-renders, it will read the state from the context, and we expect it's consistent. (No evidence, but that's how RR6 would have worked.)

Note, this still doesn't solve the stale props issue in useSelector.

Regret

If we had this solution half a year ago, we would have been able technically to base RR6 to add hooks support. (Updating peer deps might still require major version up, though.) It's too late and this doesn't provide any constructive suggestion now, but it may give a hint hopefully.

Final note

I read once again the 14110 issue, and found @sebmarkbage 's comment.

E.g. setting changed bits to zero and then manually force updating the relevant children.

It's already noted. I didn't have enough understanding back then. But, this is it.

state as object

Hi,
I tried to use an object in my state but it seems like there is an issue, I have to dispatch three times to get the updated state in my component.

This is the code:

const initialState = {
  game: { pin: null }
};

export const reducer = (state = initialState, action) => {
  console.log('state', state);
  switch (action.type) {
    case 'setNewGame':
      return {
        ...state,
        game: {
          ...state.game,
          pin: action.gamePin
        }
      };
    default:
      return state;
  }
};

possibility that the state from the store is inconsistent

regarding:

// run callback in each commit phase in case something has changed.
// [CAUTION] Limitations in subscription in useEffect
// There is a possibility that the state from the store is inconsistent
// across components which may cause problems in edge cases.

Are you referring to the react-redux issue that makes that library so much more complicated where they have to deal with "zombie components" ??

Truthfully, I never fully understood the issue. I always got close, but never spent the time to reproduce it so i could see it for myself.

If we have that issue still, unfortunately we have to solve it to be taken seriously. I recall that did it with nested usage of context in order to track the relationship between parent HOCs and descendant HOCs. So if, a parent is unsubscribed, insure the child also unsubscribes even if it has stale state that results in it it still rendering. Something like that I think was the issue.

Discussions about proxy-polyfill

From Twitter: https://twitter.com/dai_shi/status/1145316559461556225

Just revisited: https://github.com/GoogleChrome/proxy-polyfill and reduxjs/react-redux#1179 Two caveats:

  1. It doesn't support has and ownKeys handler.
  2. It doesn't detect accessing new properties. In other words, it would work only if state is only accessed by get with existing properties.

Suppose state = { counter1: 0 }, with proxy-polyfill:

  1. 'counter1' in state can't be trapped.
  2. state.counter2 can't be trapped.

Implement direct mutation support?

Posted this initially to #10 but it's offtopic over the so I'm pulling it here.

Have you considered supporting mutating the state too? I think this method could be used to implement very mobx like api for Redux.

Eg. add support for this:

function Counter() {
	const state = useReduxState();
	return <button onClick={() => state.count++}>{count}</button>;
}

The implementation could go like this:

  1. User does state.foo.bar = 1 in a event handler
    • it should be banned during the render tick
  2. Record that change as a immer patch {"op": "replace", "path": ["foo", "bar"], "value": 1}
  3. Create redux action from like
{
  type: "IMMER_PATCH",
  patch:  {"op": "replace", "path": ["foo", "bar"], "value": 1},
}
  1. And apply it using applyPatches from immer in a reducer. It would support all the redux goodies: Devtools, Time-travel, action serialization etc.

Kinda getting excited about this ๐Ÿ˜ƒ

getUntrackedObject always returning null

When using the recommended pattern getUntrackedObject to avoid using the proxied state outside render I'm finding the getUntrackedObject always returns null.

Contrived example:

const MyComp = () => {
  const state = useTrackedState()
  const dispatch = useDispatch()

  return (
    <button onClick={() => dispatch({ type: 'FOO', value: getUntrackedObject(state) })}>
      Update
    </button>
  )
}

Tracing through the method, I'm finding that isPlainObject(obj) returns true, but the obj[GET_ORIGINAL_SYMBOL] returns undefined and thus causes the method to return null rather than the untracked object.

Not sure if this is a bug or if I may be mis-using it somehow?

Selector interface support

Since many people are interested in the selector interface, I start thinking about it.

from there: #3 (comment)

We shouldn't track the state usage in selectors. We don't need to track it if only the result is important.
That brings me an idea to provide another hook, which is much like something many have been discussing.

const Pair = props => {
  const prevValue = useRef(null);
  const mapState = state => {
    const { value, name } = state[props.sliceId][props.pairId];
    const direction = value > prevValue.current ? "up" : "down";
    return { value, name, direction };
  };
  const { value, name, direction } = useReduxStateMapped(mapState);

  useEffect(() => {
    prevValue.current = value;
  });
  return (

It works somewhat magically. Closures are fine.

Concurrent mode?

From the comment by @MrWolfZ : reduxjs/react-redux#1179 (comment)

it makes render impure since through the proxy it writes to a mutable reference (yes, it only assigns ref.current inside effects but e.g. trapped.reset() etc. during render mutate the objects inside those references); that said, while this means it is not strictly pure, all mutations your library currently performs are "predictable" and reproducible, so the render still has the pure property of same inputs = same outputs

That's what I thought. Not technically pure, but reproducible. So, flushing rendering results in concurrent mode is fine.
Note: WeakMaps are there for performance reasons. It works without them.

Final note regarding concurrent mode: As @markerikson noted in a source code comment, I believe as well that any solution which accesses store.getState() during render will have issues with concurrent mode, which includes your library.

That's something I thought doubtful too. Let me learn about it.

Question: Ease of gradual transition to hooks concern

@dai-shi, et al., let me express concern on lack of information on transition support (from react-redux to reactive-react-redux).

Scenario: I am currently developing and maintaining a rather large client-side application with centralized store managed by redux. With all this new fuzz like hooks and what not, I tend to want to write new components using the new technology elements. However, I want to leave working parts, especially the very basal parts, like the application root nodes as much intact as possible, that's one. Also, I want to be able to share an existing redux's store onto the reactive-react-redux goodies. Expecting that useReduxDispatch would produce me the same dispatch() function as react-redux's connect() does.

This can be achievable either by using the same Redux provider (as in react-redux) - or exposing the package's own connect() function what would fallback to react-redux functionality.

I don't want to have duplicated stores, or partially split stores (between hooks supporting components and the older ones). Or nesting provider components. Or anything of the sort.

Thoughts?

SSR and `useLayoutEffect` issues warning in dev mode

The recent change in v4.6.0 will result in the following warning in an SSR rendered app in development:

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://fb.me/react-uselayouteffect-ssr for common fixes.
    in Provider (at _app.tsx:188)

I think you should be able to add another condition in the new condition checking whether typeof window === 'undefined'

Recommended way to log state

Noticed that when running console.log(state) it returns a proxy. What's the suggested way of logging out state? is it possible to unwrap the proxy that's returned from a useReduxState call?

"Please use <Provider store={...}>..." exception unable to track down root cause

I'm getting the following error after dispatching an action (this is dispatched using the standard dispatch from connect react-redux).

image

I'm currently only using reactive-react-redux in one component and have checked that I am not dispatching any reactive state.

I've wrapped my app inside of two providers, the normal react-redux one and the reactive-react-redux one.

image

Any pointers?

useTrackedState on an array does not trigger a rerender of FlatList with the extraData prop

Grabbing large array from state with tons of nested objects inside of it:

const trackingBoardList = useTrackedState<iAppState>().trackingBoardAndSchedule.trackingBoardList;

Then passing this to the ExtraData prop of FlatList

 <FlatList extraData={trackingBoardList} />

In the docs, FlatList is supposed to re-render when extraData detects a change. FlatList does not re-render with useTrackedState. Side note: nowhere in the RN Flatlist docs is it specified that extraData must be a primitive. That being said, if I try to track the .length of my array it does work (but obviously only when the amount of array elements change, not when the objects inside the array have changed properties).

'Please use <TrackedState...>' exception. Need help!

I'm getting the error and my page crashes. It appears that it is the get state(){ error that is being thrown.

I haven't quite managed to track down what piece of my code it is that is causing it, but it seems to be some dispatch.

What do these exception-messages even mean?

const warningObject = { get state() { console.trace(); throw new Error('Please use <TrackedProvider ...>'); }, get dispatch() { throw new Error('Please use <TrackedProvider ...>'); }, get subscribe() { throw new Error('Please use <TrackedProvider ...>'); }, };

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.