简体   繁体   中英

Possible to use handleChange function outside of react component?

I'm using a simple stateless function as a react component with a react hook state. Also I would like to keep every function in a separated place to make testing easier and to make the code more readable if the function gets a bit bigger.

So in this example the handleChange function should do a bit more then just set the state value. But if I put it outside of the function, I do not have access to the setMessage function and the props of the component.

Is this anyway useful or is it a wrong react way?

example.js

import React, { useState } from 'react'

export function handleChange (event) = {
    // do something...
    // how to get props?
    setMessage('new'); // is not defined at this place
}

export default function Message = (props) => {
    const [message, setMessage] = useState('');

    return (
        <input
            type="text"
            value={message}
            placeholder="Enter a message"
            onChange={handleChange}
        />
    );
};

You can use currying for this

export const handleChange = setState => event => {
  setState('new'); 
}

and in the component

export default function Message = (props) => {
const [message, setMessage] = useState('');
const reactOnChange = useCallback(handleChange(setMessage),[]);
return (
    <input
        type="text"
        value={message}
        placeholder="Enter a message"
        onChange={reactOnChange }
    />
  );
};

Alternatively:

export const handleChange = relevantData => {
  return 'new'; 
}


export default function Message = (props) => {
const [message, setMessage] = useState('');
return (
    <input
        type="text"
        value={message}
        placeholder="Enter a message"
        onChange={e => setMessage(handleChange(getRelevantDataFrom(e)))}
    />
  );
};

This gives a function a total separation from react.

Nesting functions inside functions does not look very well. If you like functional approach you can pipe them

   onChange={pipe(getRelevantDataFrom, handleChange, setMessage)}

where

const pipe = (...functions) => x => functions.reduce((acc, f) => f(acc), x)

I can see and agree that separating your logic from your component can be beneficial for testing (though sometimes testing the component itself is also valuable so this is not a hard rule by any means).

In your case, I think you're trying to draw the line a little to far away from React. What I would suggest is to still have "handleChange" inside of the component, but create a new function outside of the component that handles the logic you want to isolate and that returns the message to set at the end. This function can take the props as a argument. So your handleChange function would take the relevant props and pass them as arguments to this function, then call setMessage with the return value of your function. Now you have a pure input/output function that you can test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM