Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selector own props #118

Closed
ghalex opened this issue Jun 20, 2019 · 9 comments
Closed

Selector own props #118

ghalex opened this issue Jun 20, 2019 · 9 comments
Labels
question Further information is requested

Comments

@ghalex
Copy link

ghalex commented Jun 20, 2019

I know you can use $store.map to select part of a store but what if I need to select a part of a store using a parameter. Example:

const $data = createStore({"alex": {age: 20, name: "Alex}, "john": {age: 30, name: "John"}})

if I have and cont id = "alex" in a component somewhere is there a use to select only alex data and get the update if that is changing ?

Using reselect I could do something like:

const getVisibilityFilter = (state, props) => state.todoLists[props.listId].visibilityFilter
@ghalex ghalex added the question Further information is requested label Jun 20, 2019
@goodmind
Copy link
Contributor

goodmind commented Jun 20, 2019

const Component = createComponent(
  props => $data.map(list => list[props.id]), 
  (props, state) => {
    return <div />
  }
)

@ghalex
Copy link
Author

ghalex commented Jun 21, 2019

Thanky you @goodmind for the answer, this will do it.

But can you do this using hooks. I connect my stores using useStore($data)

@Laiff
Copy link
Contributor

Laiff commented Jul 1, 2019

@ghalex You can use Gate and combine to cache value

const OwnGate = createGate();

const DataSlice = combine(
  SomeStoreWithData, 
  OwnGate.state, 
  (data, props) => selectSliceFromData(state, props)
)

const SomeComponent = (props) => {
  useGate(OwnGate, props);
  return <InnerComponent />
}

const InnerComponent = () => {
  const dataSlice = useStore(DataSlice);

  return <div>{dataSlice}</div>
}

May be it should work in one component too.

@ghalex
Copy link
Author

ghalex commented Jul 1, 2019

Hi @Laiff, thx for the replay but I think I found the solution myself, I will posted here if someone else is searching for something like this:

const Component = ({ id }: Props) => {
  const user = useStore(store.$currentUser);
  const company = useStore(store.$all.map(all => all.find(c => c.id === id)));
  // here I have the company selected from the $all store, and it works if $all store changes
}

and this is using hook useStore

@Laiff
Copy link
Contributor

Laiff commented Jul 2, 2019

@ghalex Nice solution, but does it recalculate stored value on changing props?

@zerobias
Copy link
Member

zerobias commented Jul 2, 2019

Yes, it is

@zerobias
Copy link
Member

zerobias commented Jul 2, 2019

we have a solution for this issue, will be published in next release of effector-react

https://github.com/zerobias/effector/blob/master/src/react/useStore.js#L26
https://github.com/zerobias/effector/blob/master/src/react/__tests__/useStore.test.js#L44

const Component = ({id}) => {
  const user = useStoreMap({
    store: users,
    keys: [id],
    fn: (users, [id]) => users[id],
  })
}

const users = createStore({
  alex: {age: 20, name: "Alex"},
  john: {age: 30, name: "John"},
})

It can be used for your own hooks

const readUserAge = id => useStoreMap({
  store: users,
  keys: [id],
  fn: (users, [id]) => users[id].age,
})

const UserAge = ({id}) => {
  const age = readUserAge(id)
}

In this example UserAge will be rerendered only when user's age is changed

@zerobias
Copy link
Member

zerobias commented Jul 2, 2019

Also maybe it makes sense to add alternative syntax, similar with official hooks.

const Component = ({id}) => {
  const user = useStoreMap(users$, (users, [id]) => {
    return users[id]
  }, [id])
}

const users$ = createStore({
  alex: {age: 20, name: "Alex"},
  john: {age: 30, name: "John"},
})

@zerobias
Copy link
Member

zerobias commented Jul 3, 2019

Method useStoreMap published in effector-react@19.1.1. (No alternative syntax yet)

@zerobias zerobias closed this as completed Jul 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants