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

Parameter in Call #196

Closed
MokDevelopment opened this issue Jul 15, 2022 · 2 comments
Closed

Parameter in Call #196

MokDevelopment opened this issue Jul 15, 2022 · 2 comments

Comments

@MokDevelopment
Copy link

Thanks for the lib.
I wanted to implement this feature but had been confronted with 2 mature issues, that let me stick to simple function in the comp file, that will be called in a static function within a page.

  1. The useHooks do not carry payloads… this is important to handle specific calls for specific instances of the same component in the same page.

  2. The hook body is more like a static independent function without context… or index. This makes it hard to bind the data two the components if there are more than just one.
    Are there any plans to modify or add payload features in the future ?

@ricokahler
Copy link
Owner

Hi @MokDevelopment,

This lib is more or less an alternative API to getStaticProps/getServerSideProps which means it is only as capable as those APIs.

The hook body is more like a static independent function without context… or index

This isn't exactly true. When you create a data hook, there is a context parameter that is the same context as the getStaticProps context or the getServerSideProps context.

import { createDataHook } from 'next-data-hooks';

// this context is the GetStaticPropsContext from 'next'
//                                                      👇
const useBlogPost = createDataHook('BlogPost', async (context) => {
  const slug = context.params?.slug as string;

  // do something async to grab the data your component needs
  const blogPost = /* ... */;

  return blogPost;
});

export default useBlogPost;

You can choose to use this context to run some code conditionally (e.g. based on captured path params or search params). You can use this lib to create a data hook that runs on multiple different pages but the context the data hook receives will differ depending which top-level page component rendered the component with the data hook.

For example, I can create a header component with a data hook and then use that header component on multiple different pages. I can also add some conditional code that looks at the context.params and changes what's returned.

import { createDataHook } from 'next-data-hooks';
import {startCase} from 'lodash';

const useHeaderData = createDataHook('Header', async (context) => {
  const data = await yourDataFetchingFunction();

  if (typeof context.params?.slug === 'string') {
    return {title: startCase(context.params.slug), data}
  }

  return {title: 'My App', data}
});

function Header() {
  const {title, data} = useHeaderData();

  return // ...
}

Header.dataHooks = [useHeaderData];

export default Header;

The useHooks do not carry payloads… this is important to handle specific calls for specific instances of the same component in the same page.

This is true. The result of data hooks cannot differ between the same component on the same page. This is by design. I like to say that this lib is an alternative API to getStaticProps/getServerSideProps because the same constraints apply.

If you have multiple instances of the same component but want the results of each component to differ, I would suggest:

  1. Creating one shared data hook for all possible instances of the component for that page. This would mean returning an array of values that correspond to every instance that should be on that page.
  2. Passing in a prop to the component. This prop would then be used to find which value from this array corresponds to the current instance.

Example:

const useUserData = createDataHook('User', async (context) => {
  const searchTerm = context.query?.q;

  // imagine this is a call to your service layer or some fetch
  const users = await getUsersFromSearchTerm(searchTerm);

  return users;
});

function User({id}) {
  const users = useUserData();

  const user = users.find((user) => user.id === id);

  // etc.
  return <>{user.name}</>
}

User.dataHooks = [useUserData];

export default User;

Are there any plans to modify or add payload features in the future ?

No, these data hooks will remain like this by nature of the lib and the underlying next.js APIs.

Note: the primary thing this lib offers is a pattern for better organizing getStaticProps/getServerSideProps but it does not offer any more capabilities over vanilla Next.js.

It might be possible in the future to offer parameterized and dynamic data hooks but it would have to work with Next.js SSR. This would require an implementation of React 18 server-side data fetching by Next.js first (which is currently unsupported). See the Next.js Layouts RFC for more info.

@MokDevelopment
Copy link
Author

Thank you very much for the detailed answer. I needing to pick up the fact, that the context comes with the hook. In this case it is of course possible to handle all of instances of the component in the same function / hook.

Thanks for making that clear.
I will have another look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants