React 组件不调用 connect redux 函数

Posted

技术标签:

【中文标题】React 组件不调用 connect redux 函数【英文标题】:React component does not call connect redux function 【发布时间】:2021-02-24 08:42:18 【问题描述】:

组件和 redux 存储的连接有一个奇怪的问题。 虽然我有 2 个组件(兄弟姐妹),但一个可以连接到 redux 商店(Pets.js),另一个不能(FeedList.js)

我会尽量解释清楚。

从上到下的结构是我的项目。

App.js:

import React,  Component, Fragment  from "react";
import  HashRouter as Router, Route, Switch  from "react-router-dom";

import  Provider as AlertProvider  from "react-alert";
import AlertTemplate from "react-alert-template-basic";

// Components
import Header from "./layout/Header";
import Dashboard from "./pets/Dashboard";
import Alerts from "./layout/Alerts";
import Login from "./accounts/Login";
import Register from "./accounts/Register";
import PrivateRoute from "./common/PrivateRoute";
import MainFeed from "./feed/MainFeed";

import  Provider  from "react-redux";
import store from "../store";
import  loadUser  from "../actions/auth";

const alertOptions = 
  timeout: 3000,
  position: "top center",
;

class App extends Component 
  componentDidMount() 
    store.dispatch(loadUser);
  

  render() 
    return (
      <Provider store=store>
        <AlertProvider template=AlertTemplate ...alertOptions>
          <Router>
            <Fragment>
              <Header />
              <Alerts />
              <div className="container">
                <Switch>
                  <PrivateRoute exact path="/" component=Dashboard />
                  <PrivateRoute
                    exact
                    path="/feed"
                    component=MainFeed
                    ...store
                  />
                  <Route exact path="/register" component=Register />
                  <Route exact path="/login" component=Login />
                </Switch>
              </div>
            </Fragment>
          </Router>
        </AlertProvider>
      </Provider>
    );
  

export default App;
// ReactDOM.render(<App />, document.getElementById("app"));

我的自定义路由组件是我将道具传递给其他组合的 PrivateRoute。

PrivateRoute.js:

import React from "react";
import  Route, Redirect  from "react-router-dom";
import  connect  from "react-redux";

const PrivateRoute = ( component: Component, auth, ...rest ) => (
  <Route
    ...rest
    render=(props) => 
      if (auth.isLoading) 
        return <h2>Loading...</h2>;
       else if (!auth.isAuthenticated) 
        return <Redirect to="/login" />;
       else 
        console.log(props);
        return <Component ...props />;
      
    
  />
);

const mapStateToProps = (state) => (
  auth: state.auth,
);

export default connect(mapStateToProps, null, null,  pure: false )(
  PrivateRoute
);

好的,Dashboard 组件中问题的奇怪部分来了,它呈现 Pets 组件一切都很好,它连接到商店。

Dashboard.js:

import React,  Fragment  from "react";
import Form from "./Form";
import Pets from "./Pets";

export default function Dashboard() 
  return (
    <Fragment>
      <Form />
      <Pets />
    </Fragment>
  );


Pets.js

import React,  Component, Fragment  from "react";
import  connect  from "react-redux";
import PropTypes from "prop-types";
import  getPets, deletePet, getAllPets  from "../../actions/pets";

import UserPetsStyle from "../../style/LayoutStyle";
import DeleteIcon from "@material-ui/icons/Delete";

import 
  Paper,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
 from "@material-ui/core";

export class Pets extends Component 
  static propTypes = 
    pets: PropTypes.array.isRequired,
    getPets: PropTypes.func.isRequired,
    deletePet: PropTypes.func.isRequired,
    getAllPets: PropTypes.func.isRequired,
  ;

  componentDidMount() 
    console.log(this.props);
    this.props.getPets();
  

  render() 
    const classes = UserPetsStyle;
    return (
      <Fragment>
        <h2>Pets</h2>
        <TableContainer component=Paper>
          <Table className=classes.table aria-label="simple table">
            <TableHead>
              <TableRow>
                <TableCell align="right">ID</TableCell>
                <TableCell align="right">Name</TableCell>
                <TableCell align="right">Race</TableCell>
                <TableCell align="right">Create At</TableCell>
                <TableCell align="right">Actions</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              this.props.pets.map((pet) => (
                <TableRow key=pet.id>
                  <TableCell align="right">pet.id</TableCell>
                  <TableCell align="right">pet.name</TableCell>
                  <TableCell align="right">pet.race</TableCell>
                  <TableCell align="right">pet.created_at</TableCell>
                  <TableCell align="right">
                    <DeleteIcon
                      onClick=this.props.deletePet.bind(this, pet.id)
                      className="btn btn-danger btn-sm"
                    />
                  </TableCell>
                </TableRow>
              ))
            </TableBody>
          </Table>
        </TableContainer>
      </Fragment>
    );
  


const mapStateToProps = (state) => (
  pets: state.pets.pets,
);

export default connect(mapStateToProps,  getPets, deletePet, getAllPets )(
  Pets
);

虽然我的 MainFeed/FeedList 甚至没有调用连接函数。

MainFeed.js:

import React,  Fragment  from "react";
import  FeedList  from "../feed/FeedList";

export default function MainFeed() 
  return (
    <Fragment>
      <FeedList />
    </Fragment>
  );


FeedList.js

import React,  Component, Fragment  from "react";
import  connect  from "react-redux";
import PropTypes from "prop-types";
import UserPetsStyle from "../../style/LayoutStyle";

import  getAllPets  from "../../actions/pets";
import 
  Paper,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
 from "@material-ui/core";

export class FeedList extends Component 
  static propTypes = 
    pets: PropTypes.array.isRequired,
    getAllPets: PropTypes.func.isRequired,
  ;

  componentDidMount() 
    console.log(this);
    // this.props.getAllPets();
  

  render() 
    const classes = UserPetsStyle;
    return (
      <Fragment>
        <h2>Pets</h2>
        <TableContainer component=Paper>
          <Table className=classes.table aria-label="simple table">
            <TableHead>
              <TableRow>
                <TableCell align="right">ID</TableCell>
                <TableCell align="right">Name</TableCell>
                <TableCell align="right">Race</TableCell>
                <TableCell align="right">Create At</TableCell>
                <TableCell align="right">Actions</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              /* this.props.pets.map((pet) => (
                <TableRow key=pet.id>
                  <TableCell align="right">pet.id</TableCell>
                  <TableCell align="right">pet.name</TableCell>
                  <TableCell align="right">pet.race</TableCell>
                  <TableCell align="right">pet.created_at</TableCell>
                  <TableCell align="right"></TableCell>
                </TableRow>
              )) */
            </TableBody>
          </Table>
        </TableContainer>
      </Fragment>
    );
  


const mapStateToProps = (state) => 
  return 
    pets: state.pets.pets,
  ;
;

export default connect(mapStateToProps,  getAllPets )(FeedList);

有什么想法吗?

为了进一步帮助您,我在 connect func 中尝试了 withRouter 方法和 pure:false 选项,但似乎没有任何变化。此外,在使用 reduxDevTools 和 DevTools 时,似乎在 FeedList.js 组件中没有调用 mapStateToProps。

感谢您的宝贵时间!

【问题讨论】:

【参考方案1】:

connect dispatch 的第二个参数应该是这样发送的:

const mapDispatchToProps = dispatch => 
  return 
    // dispatching plain actions
    getAllPets: () => dispatch(getAllPets())
   
  

【讨论】:

如果你的意思是在最后一个组件 FeedList.js ,那么什么都不会发生。当我在 ComponentDidMount() 函数中使用 console.log(this.props) 时,props 为 null,pets[] 数组和 getAllPets 函数都没有。【参考方案2】:

我真的解决了。 问题是我不应该导入带有括号 ( FeedList ) 的组件 FeedaList。

【讨论】:

以上是关于React 组件不调用 connect redux 函数的主要内容,如果未能解决你的问题,请参考以下文章

connect redux函数不能与react-native一起使用

React-redux框架之connect()与Provider组件 用法讲解

react-redux connect 和 redux 数据的组件生命周期顺序

React×Redux——react-redux库connect()方法与Provider组件

react-redux的connect()方法

深入理解Redux之手写React-Redux