【问题标题】:Unable to redirect on button click React.js (using context provider)无法在按钮单击 React.js 时重定向(使用上下文提供程序)
【发布时间】:2021-06-09 19:56:49
【问题描述】:

我是 React 新手,在从我的 API 获得响应后,我一直在尝试重定向到不同的组件。

我尝试过使用历史记录、位置和重定向,但重定向从未发生。

另外,当我使用以上所有方法时,我会得到undefined

我不确定这是否是因为我的 App 是在 Router 之外定义的,如果这是我仍然无法解决问题的原因。

这是我的代码:

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

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

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 }

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

【问题讨论】:

    标签: javascript reactjs react-router react-context react-functional-component


    【解决方案1】:

    如果我正确理解了一个主题,您的 AppProvider 位于组件树中的路由器上方。因此,react 路由器无法将其依赖项注入您的 AppProvider。如果你想访问 react-router API,例如 useHistory hook 或其他,你应该从 Router 子节点之一调用它,然后它会起作用。

    【讨论】:

    • 感谢您的回复,是的,我的AppProvider位于路由器上方。但是,我不完全理解如何在其中一个路由器子节点中使用UseHistory。您能否提供一个参考我的代码的示例?另外,有什么方法可以在我的 Provider 中进行重定向?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    • 2022-08-05
    • 2020-03-11
    相关资源
    最近更新 更多