Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply useEffect based on form submission in React?

I am trying to make an API call inside a functional component, based on a form submission:

const SearchForm = () => {
    const [keywords, setKeywords] = useState('')
    const [fetchedData, setFetchedData] = useState('')

    const handleSubmit = (e) => {
        e.preventDefault();
        useEffect(() => {
            async function fetchData() {
                const {data} = await axios.post('http://127.0.0.1:8000/api/posts/', keywords)
                setFetchedData(data);
            }
            fetchData()
        })
    }

    return (
        <div>
            <form onSubmit={ handleSubmit }>
                <div className='input-field'>
                <input placeholder="Search whatever you wish" 
                    type="text"
                    value={keywords}
                    onChange={(e) => setKeywords(e.target.value)}
                />
                </div>
            </form>
        </div>
    )
}

However when I try this, the following error shows up:

React Hook "useEffect" is called in function "handleSubmit" which is neither a React function component or a custom React Hook function  react-hooks/rules-of-hooks

How do I carry this out?

like image 974
iscream Avatar asked Jun 07 '20 16:06

iscream


People also ask

Can I use useEffect in return?

The useEffect Hook is built in a way that we can return a function inside it and this return function is where the cleanup happens. The cleanup function prevents memory leaks and removes some unnecessary and unwanted behaviors.

How useEffect is triggered?

By default useEffect will trigger anytime an update happens to the React component. This means if the component receives new props from its parent component or even when you change the state locally, the effect will run again.

How does useEffect () hook gets executed?

To trigger the useEffect hook before unmounting the component from the screen, we can return a function from the callback function. The function returned by the callback will be executed before that component is unmounted.

How do you trigger useEffect only once?

Side Effect Runs Only Once After Initial Render You do not want to make this API call again. You can pass an empty array as the second argument to the useEffect hook to tackle this use case. useEffect(() => { // Side Effect }, []); In this case, the side effect runs only once after the initial render of the component.


1 Answers

Because it is not how useEffect used for. You don't need to call it inside handler either.

From the documentation :

Only Call Hooks from React Functions Don’t call Hooks from regular JavaScript functions. Instead, you can:

✅ Call Hooks from React function components.

✅ Call Hooks from custom Hooks (we’ll learn about them on the next page). By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.

If you want fetch data onload of your functional component, you may use useEffect like this :

  useEffect(() => {
    fetchData()
  }, [])

And you want your fetch call to be triggered with button click :

const handleSubmit = e => {
    e.preventDefault()
    fetchData()
  }

So whole code will look like :

const SearchForm = () => {
  const [keywords, setKeywords] = useState('')
  const [fetchedData, setFetchedData] = useState('')

  async function fetchData() {
    const { data } = await axios.post(
      'http://127.0.0.1:8000/api/posts/',
      keywords
    )
    setFetchedData(data)
  }

  useEffect(() => {
    fetchData()
  }, [])

  const handleSubmit = e => {
    e.preventDefault()
    fetchData()
  }

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <div className="input-field">
          <input
            placeholder="Search whatever you wish"
            type="text"
            value={keywords}
            onChange={e => setKeywords(e.target.value)}
          />
        </div>
      </form>
    </div>
  )
}

like image 163
Kerem atam Avatar answered Nov 16 '22 02:11

Kerem atam