2

Is there way to get context in usual Javascript function (in function which is not being rendered)?

I have function which doesn't render anything (it downloads .csv) which uses hook (using hook is not correct solution)

const archiveExportCSV=async(tasks)=> {
    let context = useContext(StaticsContext);
    //... some code which uses context
    Helpers.download(csv,'test.csv','data:text/csv;charset=utf-8');
};

and I am calling it in component:

<button type="button" 
        className="btn-reset"
        title="export to .csv"
        onClick={()=>archiveExportCSV(tasks)}>

It is wrong because function is neither a React function component or a custom React Hook function. Is there any way how get context in callable function or I have to pass arguments from context manually as arguments?

4
  • 1
    hooks can only be used inside of a functional component bur not inside of a handler. You need to pass the relevant context to the function as arguments. Commented Aug 9, 2019 at 13:35
  • @trixn So as I wrote there is no other way than passing it as arguments like archiveExportCSV(tasks, somethingFromContext) right? Commented Aug 9, 2019 at 13:36
  • 1
    Yes that is how you need to do it. There is no other way. Commented Aug 9, 2019 at 13:37
  • Technically, it does not have to be an argument, just a variable in scope (including closure variables), but anything more complicaded would be impractical for this use case. Commented Aug 9, 2019 at 13:49

2 Answers 2

1

You can't call hooks in a handler but you can pass the context to your function when it gets called. Hooks need to be called unconditionally and on every render of your component in the same order as react references them by that. Having them in a handler violates that:

const MyComponent = ({tasks}) => {
    const context = useContext(StaticsContext);
    const handleClick = useCallback(() => archiveExportCSV(tasks, context), [tasks, context]);

    return (
        <button 
            type="button" 
            className="btn-reset"
            title="export to .csv"
            onClick={handleClick}
        >
            Click me
        </button>
    );
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for explanation. Didn't realize that button can be part of export component which gives me valid React component where I can use Hooks. So the export function can be part of the button component or called by useCallback().
1

Since you are looking for alternatives to explicit arguments - if a function can be created INSIDE a component, it can access all variable in scope (a.k.a. a closure):

const MyComponent = () => {
  const context = useContext(StaticsContext);

  const archiveExportCSV = async(tasks) => {
    //... some code which uses context
  };
  ...
}

2 Comments

Thank you for idea. It's simpler solution than using useCallback hook.
useCallback is a performance optimization, it shouldn't affect any business logic whether it's used or not

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.