使用 React 路由器时无法从 props 访问 redux 操作
Can't access redux actions from props when working with react router
我对 React 和 redux 还很陌生,当与 React 路由器一起使用时,我在从 props 访问我的 redux 操作时遇到了问题。我已经尝试了很多格式化配置,但无论我尝试什么,道具都只有反应路由器功能,即历史、匹配和位置。我正在使用 connected-react-router 但它似乎没有做任何事情。我已经能够从我的导航菜单组件访问 redux 操作,所以我认为那里没有任何问题。
这是我尝试过的最新配置示例:
const mapStateToProps = (state) => {
return { isSignedIn: state.auth.isSignedIn }
}
const ConnectedApp = connect(
mapStateToProps,
{ signOut, signIn }
)(App);
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter basename={baseUrl} history={history}>
<ConnectedApp />
</ConnectedRouter>
</Provider>,
rootElement);
这是应用程序内部:
class App extends Component {
static displayName = App.name;
render () {
return (
<Layout>
<Route exact path='/' component={(props) =><Home {...props}/>} />
<Route exact path='/LogInExisting' component={(props) => <LogInExisting {...props} />} />
<Route exact path='/LogInCreate' component={(props) => <LogInCreate {...props} />} />
</Layout>
);
}
}
下面是尝试访问登录操作的内容:
const LogInExisting = (props) => {
const history = useHistory();
const handleSignIn = async (e) => {
e.preventDefault()
var data = {
UserName: document.getElementById('login').value,
Password: document.getElementById('password').value
}
var response = await fetch('LogInExistingUser', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
var respData = await response.json();
if (!respData.success) {
//TODO: Error handling
} else {
props.signIn();
history.push('/')
}
}
我觉得我遗漏了一些明显的东西,但我真的需要一些帮助。
您在使用 Route
组件的 component
属性函数。
<Route
exact
path='/LogInExisting'
component={(props) => <LogInExisting {...props} />}
/>
缺少的是传递给App
的道具的传递。
<Route
exact
path='/LogInExisting'
component={(routeProps) => <LogInExisting {...routeProps} {...this.props} />}
/>
您不想在 component
属性上使用匿名函数,因为这将在每次 App
渲染时重新挂载路由组件。相反,使用 render
道具功能,它适用于此用例。有关更多 in-depth 解释,请参阅 Route render methods。
<Route
exact
path='/LogInExisting'
render={(routeProps) => <LogInExisting {...routeProps} {...this.props} />}
/>
尽管如此,您正在使用 Redux,它是使用 React Context API 构建的,它解决了“props drilling”的问题。你不应该像这样将你的 redux 状态和动作作为道具传递下去。在本地 connect
HOC 中包装路由组件。
<Route exact path='/LogInExisting' component={LogInExisting} />
登录现有
const mapStateToProps = (state) => ({
isSignedIn: state.auth.isSignedIn,
});
const mapDispatchToProps = { signOut, signIn };
export default connect(mapStateToProps, mapDispatchToProps)(LogInExisting);
因为 LogInExisting
是一个函数组件,你可以使用 useDispatch
和 useSelector
钩子而不是 connect
HOC。
import { useDispatch, useSelector } from 'react-redux';
import { signIn } from '../path/to/actions';
const LogInExisting = (props) => {
const dispatch = useDispatch();
const isSignedIn = useSelector(state => state.auth.isSignedIn);
const history = useHistory();
const handleSignIn = async (e) => {
e.preventDefault();
...
if (!respData.success) {
//TODO: Error handling
} else {
dispatch(signIn());
history.push('/');
}
}
我对 React 和 redux 还很陌生,当与 React 路由器一起使用时,我在从 props 访问我的 redux 操作时遇到了问题。我已经尝试了很多格式化配置,但无论我尝试什么,道具都只有反应路由器功能,即历史、匹配和位置。我正在使用 connected-react-router 但它似乎没有做任何事情。我已经能够从我的导航菜单组件访问 redux 操作,所以我认为那里没有任何问题。
这是我尝试过的最新配置示例:
const mapStateToProps = (state) => {
return { isSignedIn: state.auth.isSignedIn }
}
const ConnectedApp = connect(
mapStateToProps,
{ signOut, signIn }
)(App);
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter basename={baseUrl} history={history}>
<ConnectedApp />
</ConnectedRouter>
</Provider>,
rootElement);
这是应用程序内部:
class App extends Component {
static displayName = App.name;
render () {
return (
<Layout>
<Route exact path='/' component={(props) =><Home {...props}/>} />
<Route exact path='/LogInExisting' component={(props) => <LogInExisting {...props} />} />
<Route exact path='/LogInCreate' component={(props) => <LogInCreate {...props} />} />
</Layout>
);
}
}
下面是尝试访问登录操作的内容:
const LogInExisting = (props) => {
const history = useHistory();
const handleSignIn = async (e) => {
e.preventDefault()
var data = {
UserName: document.getElementById('login').value,
Password: document.getElementById('password').value
}
var response = await fetch('LogInExistingUser', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
var respData = await response.json();
if (!respData.success) {
//TODO: Error handling
} else {
props.signIn();
history.push('/')
}
}
我觉得我遗漏了一些明显的东西,但我真的需要一些帮助。
您在使用 Route
组件的 component
属性函数。
<Route
exact
path='/LogInExisting'
component={(props) => <LogInExisting {...props} />}
/>
缺少的是传递给App
的道具的传递。
<Route
exact
path='/LogInExisting'
component={(routeProps) => <LogInExisting {...routeProps} {...this.props} />}
/>
您不想在 component
属性上使用匿名函数,因为这将在每次 App
渲染时重新挂载路由组件。相反,使用 render
道具功能,它适用于此用例。有关更多 in-depth 解释,请参阅 Route render methods。
<Route
exact
path='/LogInExisting'
render={(routeProps) => <LogInExisting {...routeProps} {...this.props} />}
/>
尽管如此,您正在使用 Redux,它是使用 React Context API 构建的,它解决了“props drilling”的问题。你不应该像这样将你的 redux 状态和动作作为道具传递下去。在本地 connect
HOC 中包装路由组件。
<Route exact path='/LogInExisting' component={LogInExisting} />
登录现有
const mapStateToProps = (state) => ({
isSignedIn: state.auth.isSignedIn,
});
const mapDispatchToProps = { signOut, signIn };
export default connect(mapStateToProps, mapDispatchToProps)(LogInExisting);
因为 LogInExisting
是一个函数组件,你可以使用 useDispatch
和 useSelector
钩子而不是 connect
HOC。
import { useDispatch, useSelector } from 'react-redux';
import { signIn } from '../path/to/actions';
const LogInExisting = (props) => {
const dispatch = useDispatch();
const isSignedIn = useSelector(state => state.auth.isSignedIn);
const history = useHistory();
const handleSignIn = async (e) => {
e.preventDefault();
...
if (!respData.success) {
//TODO: Error handling
} else {
dispatch(signIn());
history.push('/');
}
}