如何使用react redux更改功能组件中的路由器历史记录



我正试图将代码库从class组件迁移到functional组件,但当我这样做时,我的历史记录(browserHistory(和重定向将停止工作。

我不知道这是我使用useEffect的方式,还是强制使用history.push?但我在RouterConnected Router上得到了一个Warning: You cannot change <Router history>。我从stateredux中得到了正确的值,当我console.log时,我可以看到位置的变化——只是history.push没有发生。

我使用的是react-reduxconnected-react-router

可能是什么问题?

使用案例:加载Facebook API,当用户使用Facebook登录时,用户会重定向到另一个页面。

此代码有效:class Component (old code)

class App extends Component {
constructor(props) {
super(props);

this.facebookInterval = undefined;
this.history = createBrowserHistory();

this.state = {
hasFB: false,
error: false,
};
}

/**
* Load the Facebook SDK
*
* @return {void}
*/
componentDidMount() {

this.facebookInterval = setInterval(() => {
if (window.FB !== undefined) {
this.setState({
hasFB: true,
});

clearInterval(this.facebookInterval);
}
}, 100);

window.fbAsyncInit = function () {
window.FB.init({
appId: process.env.REACT_APP_NEW_MESSENGER_APP_ID,
autoLogAppEvents: true,
xfbml: true,
version: 'v3.3',
});
};

(function (d, s, id) {
var js,
fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.id = id;
js.src =
'https://connect.facebook.net/en_US/sdk.js?xfbml=1&version=v9.0&appId=' +
process.env.REACT_APP_NEW_MESSENGER_APP_ID;
fjs.parentNode.insertBefore(js, fjs);
})(document, 'script', 'facebook-jssdk');
}


// [NOTE]: This works when using the class component
// the redirect happens

componentWillUpdate = (nextProps, nextState) => {
console.log('nextProps.redirect', nextProps.redirect)
console.log('nextProps', nextProps)
console.log('nextState', nextState)

if (nextProps.redirect !== undefined && nextProps.redirect !== '/') {
this.history.push(nextProps.redirect);
}
};

render() {
const { t } = this.props;

if (this.state.hasFB) {
return (
<>
<Elements stripe={stripePromise}>
<ConnectedRouter history={this.history}>{routes}</ConnectedRouter>
</Elements>
</>
);
} else {
return null;
}
}
}

const mapStateToProps = (state) => {

let isLoading = state.siteR.isLoading ? 'open' : 'close';


let data = {
redirect: state.siteR.location,
isLoading: isLoading,

user: state.userR[state.userR.id],
id: state.userR.id,
};

if (state.userR[state.userR.id] !== undefined) {
data.models = state.userR[state.userR.id].models;
}

return data;
};

const mapDispatchToProps = (dispatch) => {
return {
// ommited_code
};
};

export default compose(
connect(mapStateToProps, mapDispatchToProps),
withTranslation(),
)(App);

相同的代码,但在功能组件上(新代码(

const App = (props) => {

console.log('props', props)
// console.log('props.redirect', props.redirect)

const [hasFB, setHasFB] = useState(false)
const [error, setError] = useState(false)
const [redirect, setRedirect] = useState(props.redirect)


const history = createBrowserHistory()
let facebookInterval = undefined

const {t} = useTranslation()

const initializeFacebook = () => {
facebookInterval = setInterval(() => {
if (window.FB !== undefined) {
setHasFB(true)
clearInterval(facebookInterval);
}
}, 100);

window.fbAsyncInit = function () {
window.FB.init({
appId: process.env.REACT_APP_NEW_MESSENGER_APP_ID,
autoLogAppEvents: true,
xfbml: true,
version: 'v3.3',
});
};

(function (d, s, id) {
var js,
fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.id = id;
js.src =
'https://connect.facebook.net/en_US/sdk.js?xfbml=1&version=v9.0&appId=' +
process.env.REACT_APP_NEW_MESSENGER_APP_ID;
fjs.parentNode.insertBefore(js, fjs);
})(document, 'script', 'facebook-jssdk');
}


// [NOTE]:  I get the right values from props.redirect
// and  the state
// the redirect just doesnt happen
const handleRedirect = () => {

if (props.redirect !== undefined && props.redirect !== '/') {
console.log('redirect on setRedirect', redirect)
setRedirect(history.push(props.redirect))
}
}

useEffect(() => {
initializeFacebook()
handleRedirect()
console.log('redirect on setRedirect', redirect)
}, [])


if (hasFB) {
return (
<>
<Elements stripe={stripePromise}>
<ConnectedRouter history={history}>{routes}</ConnectedRouter>
</Elements>
</>
);
} else {
return null;
}
}


const mapStateToProps = (state) => {

let isLoading = state.siteR.isLoading ? 'open' : 'close';
let showModelSelect = state.modelR.showModelSelect ? 'open' : 'close';
let showModelAdd = state.modelR.showModelAdd ? 'open' : 'close';

let data = {
redirect: state.siteR.location,
isLoading: isLoading,

user: state.userR[state.userR.id],
id: state.userR.id,
};

if (state.userR[state.userR.id] !== undefined) {
data.models = state.userR[state.userR.id].models;
}

return data;
};

const mapDispatchToProps = (dispatch) => {
return {
// ommited_code
};
};

export default compose(
connect(mapStateToProps, mapDispatchToProps),
withTranslation(),
)(App);

我试图切换到的路线

const routes =  (
<div>
<Switch>
<SentryRoute exact path='/' component={UserLogin} />
<SentryRoute exact path='/user' component={Profile} />
{/* // omited_code */}
</Switch>
</div>
)
export default routes;

从文档中,您似乎可以在connect函数中使用额外的params。

import { push } from 'connected-react-router';
/* code stuffs */
props.push('/home');
export default connect(null, { push })(Component);

https://github.com/supasate/connected-react-router/blob/master/FAQ.md#with-反应还原

最新更新