fgerschau / comments

1 stars 0 forks source link

react-hooks-separation-of-concerns/ #18

Open utterances-bot opened 2 years ago

utterances-bot commented 2 years ago

Separation of concerns with React hooks

Separation of concerns is a common topic in software development. Learn how you can apply this concept to React with custom hooks.

https://felixgerschau.com/react-hooks-separation-of-concerns/

jimmyhuang commented 2 years ago

Shouldn't your custom hook take a base and exponent as arguments?

hiredgunhouse commented 2 years ago

Separating concerns is a very fine idea, but separating a blog post from metadata like publication date is not ;P Now a more serious comment, one thing I do not like is that your hook is polluted with web concerns like preventDefault() or target.value, I may be wrong but to me those are presentational concerns, but it's probably also a matter of taste :)

fgerschau commented 2 years ago

@jimmyhuang why should they? I am using the hook to contain all business logic, including the base and exponent stored in useState.

@hiredgunhouse yeah, I'll need to change that at some point haha

I'm curious how you would suggest dealing with such things as target.value. Would you create one handler in the component that calls a function from the custom hook?

jimmyhuang commented 2 years ago

It provides more flexibility by allowing it to be used a custom reusable hook. I guess for your demonstration purposes, it is fine to hardcode the base and exponent values. In practice, I find it common for a hook to take params (e.g. an api fetching hook that takes different URIs).

fgerschau commented 2 years ago

@jimmyhuang I agree with this approach for reusable hooks; I would usually call them inside the custom hook I create for a specific component.

Maybe the example is too simple because the hook only does one thing. If I wanted it to be usable by other components, I would remove the UI-specific code and maybe make it accept params as well.

huykon commented 2 years ago

This work well on pwa-studio project by magento. That's good

wengjincheng commented 2 years ago

Well practice , It has the very meaning to me. Thanks!

TTDrazy commented 2 years ago

woo,this writing method is the same in VUE3 using the Composition API

williamfridh commented 2 years ago

Great stuff! I'm currently doing some resarch on how people choose to handle this and found your article great. Keep up the good work! :)

fgerschau commented 2 years ago

@williamfridh thanks :)

lofayo commented 2 years ago

Could share your theme with me ? Thanks!

Maximilon commented 2 years ago

@fgerschau I'm curious how you would suggest dealing with such things as target.value. Would you create one handler in the component that calls a function from the custom hook?

Yeah absolutely I would. You could also use setters to call the custom hook function in your internal component:


import { useState } from 'react';

function useSummation() {

const [base, setBase] = useState(null); const [exponent, setExponent] = useState(null);

const base = (x) => setBase(x); const exponent = (y) => setExponent(y);

return { setters: { base, exponent } }; }

export default useSummation


const { setters: { base, exponent } } = useSummation();

const handleBaseChange = (e) => { e.preventDefault(); base(e.target.value); }; const handleExponentChange = (e) => { e.preventDefault(); exponent(e.target.value); };

gabrielmlinassi commented 2 years ago

@fgerschau Nice pattern, I really liked it.

I saw some people talking about the reusability of it in the comments, however I think this hook is meant to be used specifically with this component and it's not supposed to be reusable. Its purpose is to separate logic from view in order to make it cleaner to read.

I went one step further and did a bit more abstraction. See the result:

const ExponentCalculator = () => {
  const { baseProps, exponentProps, result } = useExponentCalculator();

  return (
    <div className={styles.blueWrapper}>
      <input
        name="base"
        type="number"
        placeholder="Base"
        className={styles.base}
        {...baseProps}
      />
      <input
        name="exponent"
        type="number"
        placeholder="Exp."
        className={styles.exponent}
        {...exponentProps}
      />
      <h1 className={styles.result}>{result}</h1>
    </div>
  );
};

See sandbox: https://codesandbox.io/s/react-separate-logic-from-view-with-custom-hook-v43i49?file=/src/exponent-calculator/useExponentCalculator.ts