TypeError: Cannot read properties of undefined (reading 'params') at Function.mapStateToProps [as mapToProps]

huangapple go评论92阅读模式
英文:

TypeError: Cannot read properties of undefined (reading 'params') at Function.mapStateToProps [as mapToProps]

问题

我遇到这个错误消息:

无法读取未定义的属性(读取 'params')TypeError:
无法读取未定义的属性(读取 'params')
在 Function.mapStateToProps 中 (作为 mapToProps)

我看到应该使用 useParams,但我无法将其适应我的代码。我使用 match.paramshistory 代码。我该如何更新这些代码以适应 react-router-dom@6

const [product, setProduct] = useState({ ...props.product });
useEffect(() => {
  if (categories.length === 0) {
    getCategories()
  }
  setProduct({ ...props.product });
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.product]);
export function getProductById(products, productId) {
  let product = products.find(product => product.id === productId) || null;
  return product;
}

function mapStateToProps(state, ownProps) {
  const productId = ownProps.match.params.productId;
  const product = productId && state.productListReducer.length > 0
    ? getProductById(state.productListReducer, productId)
    : {}
  return {
    product: product,
    products: state.productListReducer,
    categories: state.categoryListReducer
  }
}

我的路由:

<Routes>
  <Route path="/" element={<DashBoard></DashBoard>}></Route>
  <Route path="/cart" element={<CartDetails></CartDetails>}></Route>
  <Route
    path="/saveproduct/:productId"
    element={<AddOrUpdateProduct></AddOrUpdateProduct>}
  ></Route>
</Routes>

我尝试使用 useParams,但这次我遇到了这个错误:

在非 React 函数组件或自定义 React Hook 函数中调用 React Hook useParams。React 组件名必须以大写字母开头。React Hook 名称必须以单词 "use" 开头 react-hooks/rules-of-hooks

function mapStateToProps(state, ownProps) {
  const { productId } = useParams();
  const product = productId && state.productListReducer.length > 0
    ? getProductById(state.productListReducer, productId)
    : {}
}
英文:

I'm having this error message:

> Cannot read properties of undefined (reading 'params') TypeError:
> Cannot read properties of undefined (reading 'params')
> at Function.mapStateToProps [as mapToProps]

I read that I should use useParams, but I couldn't adapt it to my code. I use match.params, history codes. How can I update this codes for react-router-dom@6?

const [product, setProduct] = useState({ ...props.product });
useEffect(() =&gt; {
  if (categories.length === 0) {
    getCategories()
  }
  setProduct({ ...props.product });
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.product]);
export function getProductById(products, productId) {
  let product = products.find(product =&gt; product.id === productId) || null;
  return product;
}

function mapStateToProps(state, ownProps) {
  const productId = ownProps.match.params.productId;
  const product = productId &amp;&amp; state.productListReducer.length &gt; 0
    ? getProductById(state.productListReducer, productId)
    : {}
  return {
    product: product,
    products: state.productListReducer,
    categories: state.categoryListReducer
  }
}

And my routes:

&lt;Routes&gt;
  &lt;Route path=&quot;/&quot; element={&lt;DashBoard&gt;&lt;/DashBoard&gt;}&gt;&lt;/Route&gt;
  &lt;Route path=&quot;/cart&quot; element={&lt;CartDetails&gt;&lt;/CartDetails&gt;}&gt;&lt;/Route&gt;
  &lt;Route
    path=&quot;/saveproduct/:productId&quot;
    element={&lt;AddOrUpdateProduct&gt;&lt;/AddOrUpdateProduct&gt;}&gt;
  &lt;/Route&gt;
&lt;/Routes&gt;

I try use useParams but I have this error this time:

> React Hook useParams is called in function mapStateToProps that is
> neither a React function component nor a custom React Hook function.
> React component names must start with an uppercase letter. React Hook
> names must start with the word "use" react-hooks/rules-of-hooks

function mapStateToProps(state, ownProps) {
  const { productId } = useParams();
  const product = productId &amp;&amp; state.productListReducer.length &gt; 0
    ? getProductById(state.productListReducer, productId)
    : {}

答案1

得分: 0

你只能在React函数和自定义React钩子中使用React钩子。useParams钩子不能在mapStateToProps函数内调用。使用connect高阶组件不再是将React组件订阅到应用程序的Redux存储的首选方法。在组件中使用useDispatchuseSelector钩子来访问dispatch函数和选择状态的片段。您将把检索产品的逻辑移动到组件中。

示例:

import { useParams } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';

export function getProductById(products, productId) {
  return products.find(product => product.id === productId) || {};
}

...

const AddOrUpdateProduct = () => {
  const dispatch = useDispatch();

  const { productId } = useParams();

  const products = useSelector(state => state.productListReducer);
  const categories = useSelector(state => state.categoryListReducer);

  useEffect(() => {
    if (!categories.length) {
      dispatch(getCategories());
    }
  }, [categories]);

  const [product, setProduct] = useState(() => getProductById(products, productId));

  useEffect(() => {
    setProduct(getProductById(products, productId));
  }, [products, productId]);

  ...
};

由于不清楚此处派生的product状态的确切用例是什么,我只是通知您,一般来说,上述代码被认为是React中的反模式。在大多数情况下,如果您发现自己编写了useState|useEffect耦合,应该改用useMemo钩子。

示例:

const product = useMemo(() => {
  return getProductById(products, productId);
}, [products, productId]);

有一些反例,例如,如果您正在填充一些本地状态,该状态在表单中使用,并且用户正在编辑本地副本,稍后将提交以更新存储中的源数据。

英文:

You can only use React hooks in React functions and custom React hooks. The useParams hook cannot be called within the mapStateToProps function. Using the connect Higher Order Component is no longer the preferred method of subscribing React components to the app's Redux store. Use the useDispatch and useSelector hooks in the component to access the dispatch function and select slices of state. You'll move the logic to retrieve a product into the component as well.

Example:

import { useParams } from &#39;react-router-dom&#39;;
import { useDispatch, useSelector } from &#39;react-redux&#39;;

export function getProductById(products, productId) {
  return products.find(product =&gt; product.id === productId) || {};
}

...

const AddOrUpdateProduct = () =&gt; {
  const dispatch = useDispatch();

  const { productId } = useParams();

  const products = useSelector(state =&gt; state.productListReducer);
  const categories = useSelector(state =&gt; state.categoryListReducer);

  useEffect(() =&gt; {
    if (!categories.length) {
      dispatch(getCategories());
    }
  }, [categories]);

  const [product, setProduct] = useState(() =&gt; getProductById(products, productId));

  useEffect(() =&gt; {
    setProduct(getProductById(products, productId));
  }, [products, productId]);

  ...
};

Since it's not clear what the exact use case is here for the derived product state, I'll just inform you that generally speaking the above is considered a React anti-pattern. In most cases if you see that you've coded a useState|useEffect coupling you should instead use the useMemo hook.

Example:

const product = useMemo(() =&gt; {
  return getProductById(products, productId);
}, [products, productId]);

There are few exceptions to this anti-pattern, for example one being if you are populating some local state that is used in a form and the user is editing the local copy which will later be submitted to update the source data in the store.

huangapple
  • 本文由 发表于 2023年6月29日 22:04:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76581796.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定