Rajdeep Chowdhuri
Rajdeep Chowdhuri

Reputation: 65

How to make http call onclick using stateless component in ReactJS?

I have a React stateless function component (SFC). I want a user to click a button and onclick a http call will be made from the SFC and when the response is received, I want to open a modal. Is it something achievable using SFC? Or do I need to keep a stateful component?

This is my code which makes the http call on load and then onClick opens the modal. But I want both the things to happen in sequence on the onClick event.

//HTTP CALL FUNCTION
function httpListCall(url) {
    const [list, setData] = React.useState(null);
    const [error, setError] = React.useState(null);
    React.useEffect(() => {
        axios
            .get(url)
            .then(function (response) {
                setData(response.data.ResultList);
            })
            .catch(function (error) {
                setError(error);
            })
    }, []);
    return { list, error };
};

//SFC
const ListContainer = () => {
    const { list, error } = httpListCall("/list.json"); //THIS IS ON LOAD NOW - I WANT TO CALL IT onClick
    const [modalShow, setModalShow] = React.useState(false);

    return(
        <React.Fragment>
            <div>
               <button onClick={() => setModalShow(true)}/> //WANT TO MAKE API CALL HERE AND THEN OPEN THE MODAL
            </div>
            <ModalWidget show={modalShow} list={advisorList} error={error} onHide={() => setModalShow(false)}/>
        </React.Fragment>
    )
}

export default ListContainer;
ReactDOM.render(<ListContainer/>, document.getElementById("app"));

I have tried to make the http call from a function but it gives me an error: "Invalid hook call. Hooks can only be called inside of the body of a function component."

Upvotes: 1

Views: 3051

Answers (2)

Janiis
Janiis

Reputation: 1576

SOLUTION (updated):

You have to follow custom hooks implementation requirement as I have mentioned in comment under your question - have to use name "use" in front of your custom hook function name and update useEffect dependencies.

function useHttpListCall(url) {
  const [list, setData] = React.useState(null);
  const [error, setError] = React.useState(null);
  React.useEffect(() => {
    axios
      .get(url)
      .then(function(response) {
        setData(response.data);
      })
      .catch(function(error) {
        setError(error);
      });
  }, [url]);
  return { list, error };
}

And update your functional component to use your custom Hook like this.

const ListContainer = () => {
  const [modalShow, setModalShow] = React.useState(false);
  const [endpoint, setEndpoint] = React.useState(null);

  const { list } = useHttpListCall(endpoint);

  const handleClick = () => {
    setModalShow(true);
    setEndpoint("https://api.github.com/users?since=135");
  };

  return (
    <React.Fragment>
      <div>
        <button onClick={handleClick}>Show modal of Github users</button>
      </div>
      {modalShow && list && (
        <div>
          {list.map(user => {
            return <div key={user.id}>{user.login}</div>;
          })}
        </div>
      )}
    </React.Fragment>
  );
};

I didn't implement modal as you did not provide the code for this component.

Fully working code is available here (for you to use as a reference): https://codesandbox.io/s/simple-custom-hook-n6ysw

Upvotes: 2

Almog Adziashvili
Almog Adziashvili

Reputation: 1

You cant use the new react hooks (useState, useEffect etc.) in a "normal" function, it has to be a function component.

You can put the hooks inside the component scope and keep the axios request in a seperate function.

Upvotes: 0

Related Questions