0

I am new to react about 3 days and I am wondering how to redirect to another componet when some condtion became true.

I am using class component which mean is the syntax as below

class LanguageOptions extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            'changed': false
        }
    }

    renderLngOptions() {
        return getLanguageOptions().reduce((rs, op) => {
            rs.push(
                <option key={op}>
                    {op}
                </option>
            )
            return rs
        }, [])
    }

    markTheStateAsNotChange() {
        this.setState((state) => {
            state.changed = false
            return state
        })

        return <Navigate to="/" replace={true} />
    }

    changeLng = (e) => {
        const options = e.target.options
        const language = options[options.selectedIndex].label
        change(language)
        this.setState((state) => {
            state.changed = true
            return state
        })
    }

    render() {
        return <div className="control has-icons-left">
            <div className="select is-primary">
                <select onChange={this.changeLng}>
                    {this.renderLngOptions()}
                </select>
            </div>
            <div className="icon is-small is-left">
                <i className="fa-solid fa-language"></i>
            </div>
        </div>
    }
}

I know how to redirect to another with functional component but in class component I am failed to find any useful resource to figure out this

What I want to do ? when the state changed is true first change the value to false then redirect to '/'

How did I defined the routers ?

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <BrowserRouter>
    <Routes>
      <Route path='/' element={<Board
        globalState={globalState}
      />}>
        <Route index element={<Board
          globalState={globalState}
        />}></Route>

        <Route path='parentalSettings' element={
          <PasswordSetting
            globalState={globalState}
          />
        }></Route>

        <Route path='mainPage' element={
          <MainPage
            globalState={globalState}
          />
        }>
        </Route>
      </Route>
    </Routes>
  </BrowserRouter>
)
OnTheRoad
  • 527
  • 6
  • 24

2 Answers2

0

"Navigate" is the component react-router provides and returns an element, you can use a shouldRedirect state property to inform the render method and return Navigate to redirect to the specified route.

class LanguageOptions extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      changed: false,
      shouldRedirect: false // make this true when redirect should be ready
    };
  }


  markTheStateAsNotChange() {
    this.setState((state) => {
      state.changed = false;
      state.shouldRedirect=true; // should redirect at this point
      return state;
    });

    
  }

  render() {

    // redirect to the route using Navigate component
    if (this.state.shouldRedirect) {
      return <Navigate to="/" replace={true} />;
    }
    return (
      <div className="control has-icons-left">
        ...
      </div>
    );
  }
}
linusw
  • 1,140
  • 3
  • 9
  • I got the error like this ```Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.``` – OnTheRoad Oct 16 '22 at 12:13
  • let me make a test first maybe it is problem of the way I wrote my other component – OnTheRoad Oct 16 '22 at 12:14
  • @OnTheRoad I just changed a few lines to show you the concept of using Navigate element. I didn't see where you call the markTheStateAsNotChange function so I can't know what causes infinite render. I can help on that end but you try first to implement this according to needs of your code. – linusw Oct 16 '22 at 12:22
  • I called the `markTheStateAsNotChange` on the `onchange` event of the `select` element – OnTheRoad Oct 16 '22 at 12:36
  • @OnTheRoad onChange calls changeLng but mark function isn't inside it. If this doesn't work, you can use the callback function of setState like the answer below, but you need to define withRouter function first to use props.navigate. Or you can use react-router 5, it works well with class components. – linusw Oct 16 '22 at 12:50
0

setState accepts a callback function which will run after the states have been changed react documentation for setState

Update your markTheStateAsNotChange to take advantage of setState callback

markTheStateAsNotChange() {
 this.setState((state) => {
   state.changed = false
   return state
  }, () => {
    this.props.history.push("/")
   })
}

changeLng = (e) => {
  const options = e.target.options
  const language = options[options.selectedIndex].label
  change(language)
    this.setState((state) => {
      state.changed = true
       return state
     }, () => {
     // redirect where you would like to redirect
    })
}
Nziranziza
  • 39
  • 5
  • Thanks for you reply. I am new to react so I actually dont follow you. How do I redirect in the callback function ? which mean what code should I write to replace the `redirect where you would like to redirect` ? Thanks. – OnTheRoad Oct 16 '22 at 12:40
  • OP didn't specify but suggests they use react router 6, props.history isn't available, props.navigate can do the job but custom withRouter HOC is needed first. – linusw Oct 16 '22 at 12:52