1

I would like to let users to move main component after they create content and I don't what methods I need to use. I wanted to use something like history but it didn't work. I am using

  • "react": "^17.0.2",
  • "react-dom": "^17.0.2",
  • "react-router-dom": "^6.2.1",
import React, { Component } from 'react';

class CreateContent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      content: {
        title: ''
      }
    }
  }

  handleInput = (e) => {
    this.setState({
      content : {
        ...this.state.content,
        [e.target.name]: e.target.value
      }
    })
  }

  addContent = async (e) => {
    e.preventDefault();
    console.log(JSON.stringify(this.state.title))
    try {
      const response = await fetch('http://localhost:9000/api/v1/content', {
        method: 'POST',
        body: JSON.stringify(this.state.content),
        mode:'cors',
        headers: {
          'Access-Control-Allow-Origin': '*',
          'Content-Type': 'application/json'
        }
      });

      if(!response.ok) {
        throw Error(response.statusText)
      }
// ******* HERE I wanted to add something like *******
      history.push('/main')
    } catch (err) {
      console.log('addContent failed -', err)
    }
  }

  render() {
    return (
      <div>
        <form onSubmit={this.addContent}>
          <input
            type="text"
            name="title"
            onChange={this.handleInput}
            value={this.state.content.title}
          />
          <input type="submit" value="submit" />
        </form>
      </div>
    )
  }
}

export default CreateContent
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
Cindy
  • 85
  • 1
  • 6
  • You need to use `React Router`. If I understood correctly, you want to user to navigate to some custom link if so use `Go To Details` Similarly, you would have some link from the detail page to come back to the `main` page. – Parag Diwan Feb 27 '22 at 08:33
  • @ParagDiwan I wanted to use it inside of the function so that I can let users to move main page after they succeed POST request. I used to use history.push but I guess it is not working anymore.. – Cindy Feb 27 '22 at 09:39

2 Answers2

1

In React Router v6, you need to use useNavigate instead of history.push().

But, since you're using class component React Router v6 it doesn't support these hooks out of the box for the class components. That is why you are receiving the error:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

But that doesn't mean you can't use it. You can recreate it using HOC:

import {
  useLocation,
  useNavigate,
  useParams
} from "react-router-dom";

function withRouter(Component) {
  function ComponentWithRouterProp(props) {
    let location = useLocation();
    let navigate = useNavigate();
    let params = useParams();
    return (
      <Component
        {...props}
        router={{ location, navigate, params }}
      />
    );
  }

  return ComponentWithRouterProp;
}

You can now wrap and export your class-based components to withRouter HOC in the very familiar way they were from v4/v5.

After that you can use useNavigate from react-router-dom v6.

const navigate = useNavigate()
navigate("/main")

Regarding your query that you've mentioned in the comment:

So should I create a separate component to add the above code or I should add the above code for each component that I want to use history? or should I add it into App.js?

To work around this issue first, create a new component withRouter as indicated above, and then wrap CreateContent component in a withRouter function, when it is exported:

export default withRouter(CreateContent)

withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.

withRouter reference in v5: https://v5.reactrouter.com/web/api/withRouter

Sanket Shah
  • 2,888
  • 1
  • 11
  • 22
  • 1
    Thank you for the explanation. I think your answer is what I am looking for and tried to apply it to my app but I am not quietly how to use it. So should I create seperate component to add the above code or I should add above code each component that I want to use history? or shoud I add it into App.js? Could you please add example? Thank you! – Cindy Feb 28 '22 at 03:36
  • I created withRouter.js file in top level(src)and copy and pasted your code. And wonder how to import that in CreateContent.js? I added `export default withRouter` in withRouter.js and `import {withRouter} from './withRouter'` and I still wrong? Thank you again! – Cindy Mar 01 '22 at 10:03
  • Are you still facing issue or it's resolved? @Cindy – Sanket Shah Mar 01 '22 at 12:05
  • 1
    Thank you for follow up with me! I was able to make it! It was really great solution @Sanket Shah ! – Cindy Mar 11 '22 at 20:38
0

you can achieve redirection in multiple ways in react.

1- just use Link from react-router-dom

<Link to={"/my-route"} />

2- you can use useNavigate from react-router-dom

const navigate = useNavigate()
navigate("/my-route")

3- you can simple use state to show/hide compoenents if

const [visibleComponent, setVisibleComponent] = useState('component1')
<Component1 isVisible={visibleComponent === 'component1'} />
<Component2 isVisible={visibleComponent === 'component2'} />
<Component3 isVisible={visibleComponent === 'component3'} />

and then you can change the component based on your logic ( setVisibleComponent('component2') to show the second component and so on ...

Aliens Dev
  • 251
  • 4
  • 5
  • so.. I want to use it inside of function like my example. Once you hit the button, you will post your content and then let users to move to main page. I tried 2. but it returns `Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:` because I am using class component(I think..) – Cindy Feb 27 '22 at 09:37
  • yes you cannot use hooks in class based components, what you can do is to create a button component, make it functionnal component so you can use hooks and then use inside it the useNavigate() – Aliens Dev Feb 27 '22 at 16:08