简体   繁体   English

无法在按钮单击 React.js 时重定向(使用上下文提供程序)

[英]Unable to redirect on button click React.js (using context provider)

I'm new to React and I've been trying to redirect to a different component after getting a response from my API.我是 React 新手,在收到 API 的响应后,我一直在尝试重定向到不同的组件。

I've tried using history, location, and Redirect, but the redirect never happens.我尝试过使用历史记录、位置和重定向,但重定向从未发生。

Also, I get undefined when using all of the above.此外,在使用上述所有内容时,我变得undefined

I'm not sure if this is because my App is defined outside the Router , if it is the reason I'm still unable to fix the issue.我不确定这是否是因为我的App是在Router之外定义的,如果这是我仍然无法解决问题的原因。

Here is my code:这是我的代码:

index.js index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { AppProvider } from './Context'
import { BrowserRouter as Router } from 'react-router-dom'

ReactDOM.render(
  <React.StrictMode>
    
    <AppProvider>
      <App />
    </AppProvider>
    
  </React.StrictMode>,
  document.getElementById('root')
);

App.js应用程序.js

import React from 'react';
import './App.css';
import {Home, JoinRoom, CreateRoom, Room } from './pages';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';

function App() {

 
 return (
   <div className="App">

     <Router>
       <Switch>
         <Route path="/" exact={true}>
           <Home />
         </Route>
         <Route path="/join">
           <JoinRoom />
         </Route>
         <Route path="/create">
           <CreateRoom />
         </Route>
         <Route path="/room/:roomCode">
           <Room />
         </Route>
       </Switch>
     </Router>    
     
   </div>
 );
}

export default App;

Context.js上下文.js

Here, in the handleRoomButtonPressed , I'm getting data from the API and trying to redirect.在这里,在handleRoomButtonPressed中,我从 API 获取数据并尝试重定向。

import React, { useState, useContext } from 'react';
import axios from 'axios';
import { Redirect, useHistory } from "react-router-dom";


const AppContext = React.createContext()

const AppProvider = ({ children }) => {

    // const history = useHistory();

    const [guestCanPause, setGuestCanPause] = useState(true);
    const [votesToSkip, setVotesToSkip] = useState(2);
    const [isHost, setIsHost] = useState(false);


    const handleVotesChange = (e) => {
        e.preventDefault();
        setVotesToSkip(e.target.value);
    }

    const handleGuestCanPauseChange = (e) => {
        e.preventDefault();
        setGuestCanPause(e.target.value)
    }

    const handleRoomButtonPressed = async (props) => {
        const roomData = { guest_can_pause: guestCanPause, votes_to_skip: votesToSkip };
        const response = await axios.post('/api/create-room/', roomData);
        console.log(response.data)
        const redirectUrl = "/room/" + response.data.code;
        console.log(props)
        return <Redirect to={redirectUrl} />
        
    }

    const getRoomDetails = async (roomCode) => {
        axios
      .get("/api/get-room?code=" + roomCode)
      .then((res) => {
        console.log(res.data)
        setVotesToSkip(res.data.votes_to_skip);
        setGuestCanPause(res.data.guest_can_pause);
        setIsHost(res.data.is_host);
      })
      .catch((err) => console.log(err));
    }
    

    return <AppContext.Provider value={{ guestCanPause, 
            votesToSkip, 
            isHost, 
            handleGuestCanPauseChange, 
            handleVotesChange, 
            handleRoomButtonPressed, 
            getRoomDetails, }}>
            {children}
       </AppContext.Provider>
}

export const useGlobalContext = () => {
  return useContext(AppContext)
}
export { AppContext, AppProvider }

The onClick is called in CreateRoom.js onClick在 CreateRoom.js 中被调用

import React, { useState, } from 'react';
import { useGlobalContext } from '../Context'
import { Link } from 'react-router-dom';
import { Button, Grid, Typography, TextField, FormHelperText, FormControl, Radio, RadioGroup, FormControlLabel } from '@material-ui/core'

function CreateRoom() {
    const defaultVotes =  2;
    const { handleGuestCanPauseChange, handleVotesChange, handleRoomButtonPressed } = useGlobalContext();

    return (
        <Grid container spacing={1}>
            <Grid item xs={12} align="center">
                <Typography component="h4" variant="h4">
                    Create A Room
                </Typography>
            </Grid>
            <Grid item xs={12} align="center">
                <FormControl component="fieldset">
                    <FormHelperText>
                        <div align="center">Guest Control of Playback state</div>
                    </FormHelperText>
                    <RadioGroup row defaultValue="true" onChange={handleGuestCanPauseChange}>
                        <FormControlLabel value="true" 
                        control={<Radio color="primary" />}
                        label="Play/Pause" labelPlacemment="bottom" />
                        <FormControlLabel value="false" 
                        control={<Radio color="secondary" />}
                        label="No Control" labelPlacemment="bottom" />
                    </RadioGroup>
                </FormControl>
            </Grid>
            <Grid item xs={12} align="center">
                <FormControl>
                    <TextField required={true}
                    type="number" onChange={handleVotesChange}
                    defaultValue={defaultVotes} 
                    inputProps={{ min: 1,
                        style: { textAlign: "center" },
                        }}
                    />
                    <FormHelperText>
                    <div align="center">Votes Required To Skip Song</div>
                    </FormHelperText>
                </FormControl>
            </Grid>
            <Grid item xs={12} align="center">
            <Button
                color="primary"
                variant="contained"
                onClick={handleRoomButtonPressed}
            >
                Create A Room
            </Button>
            </Grid>
            <Grid item xs={12} align="center">
            <Button color="secondary" variant="contained" to="/" component={Link}>
                Back
            </Button>
            </Grid>
        </Grid>
    )
}

export default CreateRoom

If I understood a subject correctly your AppProvider is located above the router in the component tree.如果我正确理解了一个主题,您的 AppProvider 位于组件树中的路由器上方。 Thus, the react router cannot inject its dependencies into your AppProvider.因此,react 路由器无法将其依赖项注入到您的 AppProvider 中。 If you want to access react-router API, such as useHistory hook or others, you should call it from one of the Router children, then it will works.如果您想访问 react-router API,例如 useHistory hook 或其他,您应该从 Router 子节点之一调用它,然后它将起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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