我正在尝试将代码库从class
组件迁移到functional
组件,但是当我这样做时,我的历史记录(browserHistory
)和重定向停止工作。
我不知道这是我使用的方式useEffect
,还是强迫history.push
?但我得到了Warning: You cannot change <Router history>
一个Router
和Connected Router
。state
我从and中获得了正确的值,并且当我只是没有发生这种情况redux
时,我可以看到该位置的变化。console.log
history.push
我正在使用react-redux
和connected-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;