使用 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 是一个函数组件,你可以使用 useDispatchuseSelector 钩子而不是 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('/');
    }
}