betula / use-between

Sharing state between React components
MIT License
285 stars 11 forks source link

How to make parameterized shareds? #13

Closed minuitagency closed 2 years ago

minuitagency commented 3 years ago

Hi Betula,

Thank you for the great idea, just trying your library and I can't figure out how to pass parameters to my useBetween hook...

For example:

` const useStreamingData = ({symbol, market = 'stocks', shouldUpdate = true}) => {

...

export const useLiveData = () => useBetween(useStreamingData());

`

Doesn't seem to work...

Thanks again,

Théo

betula commented 3 years ago

Hi Théo,

It's nice to hear that you are using "use-between" in your projects and I will be happy to suggest a possible solution to your task.

Your original hook is

const useStreamingData = ({symbol, market = 'stocks', shouldUpdate = true}) => {

As I understood from the task, it is required to share the state of the "useStreamingData" hook between the groups of components, depending on the call parameters.

That is, the desired result of using would be like this:


// This is a call to get the shared state in some place of code
const data1 = useSharedStreamingData({ symbol: "A", shouldUpdate: false });

// And when you call this function with the same parameters anywhere else in the code, 
// the result is expected to be share (and therefore equal).
const data2 = useSharedStreamingData({ symbol: "A", shouldUpdate: false });

console.assert(data1 === data2) // equals

Task solving code:

import memoize from "memoizee";

const useStreamingDataMemoized = memoize((symbol, market, shouldUpdate) => {
  // Thanks to the memoization tool, we got all the closure parameters we need.
  return () =>
    // Parameterized shared hook here.
    useStreamingData({
      symbol,
      market,
      shouldUpdate
    });
});

// As a result, we need to make a separate shared state for each set of arguments for calling the "useStreamingData" hook.
export const useSharedStreamingData = ({ symbol, market, shouldUpdate }) => {
  return useBetween(useStreamingDataMemoized(symbol, market, shouldUpdate));
};

Since the "use-between" hook takes a function without arguments, and for each such function only one shared state is created, we need to create a new function for each unique set of parameters. And standard memoization technique helps us in this. In this example, I used memoizee as it looks good enough, but you can use another memoization implementation as you wish.

The semantics of use, as I understood from the task, is expected to be the following.

function View({ symbol }) {
  const data = useSharedStreamingData({
    symbol
  });
  return <p>{data}</p>;
}

export default function App() {
  return (
    <>
      <View symbol="A" />
      <View symbol="B" />
      <View symbol="B" />
      <View symbol="A" />
    </>
  );
}

In this example, we have connected four React components, but only two shared states are used between them, for the "symbol" value equal to "A" and "B" respectively.

Edit on CodeSandbox

I hope my answer is good for solving your task! But if not, please tell me more about the behavior you require.

Thanks for using "use-between", Slava

minuitagency commented 3 years ago

Hi Betula,

Thank you so much to have taken the time to write such an extensive answer, it works perfectly and solved a problem our team had for months,

Thanks again,

Théo

betula commented 3 years ago

Thanks for the question! This helps me to better understand the challenges faced by the use-between team. Thank you for helping to share our experience with people!