React useSelector第一次返回未定义,然后一切正常

时间:2020-06-23 16:07:30

标签: node.js reactjs express redux react-redux

所以我正在使用MERN堆栈制作一个微型电子商务应用程序,我正在使用其ID为每个卖家获取商品,因此他是唯一可以编辑或删除自己的商品的人,

在我的组件中,我从用户的redux状态获取用户的ID,然后使用该ID为每个登录的卖方获取产品。(在useEffect中) 因此获取产品取决于用户,并且始终会加载用户,并且无需在登录后获取该产品。

问题是,只有在我登录并渲染该组件后才第一次给我 TypeError:products.map不是函数。但是如果我刷新页面就可以了 因此,即使用户在那里,也看不到产品首次出现idk的原因,并且没有ID来启动提取功能。

function EditProducts() {
  const { user } = useSelector(state => state.userrr);
  const { loading, products } = useSelector(state => state.userProductsss);

  const dispatch = useDispatch();

  useEffect(() => {
    console.log(user);
    console.log(products);

    if (!user) {
      return;
    } else {
      let id = user._id;
      dispatch(fetchUserProducts(id));
    }
  }, [dispatch, user]);

  const deleteIt = id => {
    dispatch(deleteProduct(id))
      .then(res => {
        toast.success(res, { position: toast.POSITION.BOTTOM_LEFT });
      })
      .catch(error => {
        toast.error(error, {
          position: toast.POSITION.BOTTOM_LEFT,
          autoClose: false
        });
      });
  };
  console.log(products);
  return (
    <Container>
      <Table striped bordered hover variant='dark'>
        <thead>
          <tr>
            <th>category</th>
            <th>Description</th>
            <th>Price</th>
            <th>Edit</th>
          </tr>
        </thead>
        <tbody>
          {loading && (
            <tr>
              <td colSpan='4'>
                <Spinner animation='border' /> loading...{" "}
              </td>
            </tr>
          )}

          {!user && !loading && (
            <tr>
              <td colSpan='4'>Please Log in to access this page</td>
            </tr>
          )}
          {products.map(product => (
            <tr key={product._id}>
              <td>{product.name}</td>
              <td>{product.description}</td>
              <td>${product.price}</td>
              <td>
                <span className='btn btn-primary mr-3'>
                  <UpdateProductForm
                    id={product._id}
                    name={product.name}
                    description={product.description}
                    category={product.category}
                    price={product.price}
                    numberInStock={product.numberInStock}
                    productImage={product.productImage}
                  />
                </span>
                <Button className='btn btn-danger' onClick={() => deleteIt(product._id)}>
                  <FontAwesomeIcon icon={faTrash} />
                </Button>
              </td>
            </tr>
          ))}
        </tbody>
      </Table>
    </Container>
  );
}

export default EditProducts;

这是我的减速器

const productReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_USER_PRODUCTS_STARTED:
      return {
        ...state,
        loading: true
      };
    case FETCH_USER_PRODUCTS_SUCCESS:
      return {
        ...state,
        loading: false,
        error: null,
        products: action.payload.products
      };
    case FETCH_USER_PRODUCTS_FAILURE:
      return {
        ...state,
        loading: false,
        error: action.payload.error,
        success: null
      };
  default:
    return state;
}
};

这是动作

export const fetchUserProducts = userId => {
  return dispatch => {
    dispatch(fetchUserProductsStarted());

    axios
      .get(`/api/product/${userId}/products`)
      .then(res => {
        dispatch(fetchUserProductsSuccess(res.data));
      })
      .catch(error => {
        dispatch(fetchUserProductsFailure(error.message));
      });
  };
};

const fetchUserProductsStarted = () => {
  return {
    type: FETCH_USER_PRODUCTS_STARTED
  };
};

const fetchUserProductsSuccess = products => {
  return {
    type: FETCH_USER_PRODUCTS_SUCCESS,
    payload: {
      products
    }
  };
};

const fetchUserProductsFailure = error => {
  return {
    type: FETCH_USER_PRODUCTS_FAILURE,
    payload: {
      error
    }
  };
};

1 个答案:

答案 0 :(得分:0)

所以问题在于useEffect无法确保在此处进行第一次渲染之前已加载用户数据:

const { user } = useSelector(state => state.userrr);

因此用户为空,因此根据用户ID无法获得产品。

我所做的是我再次将用户加载到组件useEffect内,以便获取用户数据。

useEffect(() => {
    dispatch(loadUser());

    const id = user ? user._id : null;
    dispatch(fetchUserProducts(id));
  }, [ dispatch, id]);