mongodb Redux在实际数据之前使用null更新状态

b1uwtaje  于 2023-02-21  发布在  Go
关注(0)|答案(2)|浏览(124)

我正在调度一个操作,该操作应该从用户那里获取输入并将其存储在数据库中,但是,当我在调度该操作后检查redux中的posts状态时,有一个空值附加到实际post之前的state数组。这阻止了我处理post数组中的实际数据。基本上我'我想知道如何防止空值被追加每次我派遣一个新的职位。这里是相关的代码

snippet和图像。
后复位器:

import { enableAllPlugins, produce } from 'immer';

enableAllPlugins();

const initialState = {
  posts: [],
  loading: false,
  error: false,
  uploading: false,
};

const postReducer = produce((draftstate, action = {}) => {
  switch (action.type) {
    case 'UPLOAD_START':
      draftstate.loading = true;
      draftstate.error = false;
    case 'UPLOAD_SUCCESS':
      draftstate.posts.push(action.data);
      draftstate.uploading = false;
      draftstate.error = false;
    case 'UPLOAD_FAIL':
      draftstate.uploading = false;
      draftstate.error = true;
    default:
      return draftstate;
  }
}, initialState);

export default postReducer;

上载发布操作:

export const uploadPost = (data) => async (dispatch) => {
  dispatch({ type: 'UPLOAD_START' });
  try {
    const newPost = await UploadApi.uploadPost(data);
    console.log('new post before', newPost);
    dispatch({ type: 'UPLOAD_SUCCESS', data: newPost.data });
  } catch (error) {
    console.log(error);
    dispatch({ type: 'UPLOAD_FAIL' });
  }
};

邮政编码:

import React, { useState, useRef } from "react";
import ProfileImage from "../../img/profileImg.jpg";
import "./PostShare.css";
import { UilScenery } from "@iconscout/react-unicons";
import { UilPlayCircle } from "@iconscout/react-unicons";
import { UilLocationPoint } from "@iconscout/react-unicons";
import { UilSchedule } from "@iconscout/react-unicons";
import { UilTimes } from "@iconscout/react-unicons";
import { useSelector, useDispatch } from "react-redux";
import { uploadImage, uploadPost } from "../../actions/uploadAction";

const PostShare = () => {
  const loading = useSelector((state) => state.postReducer.uploading);
  const [image, setImage] = useState(null);
  const imageRef = useRef();
  const desc = useRef();
  const dispatch = useDispatch();

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

  // handle Image Change
  const onImageChange = (event) => {
    if (event.target.files && event.target.files[0]) {
      let img = event.target.files[0];
      setImage(img);
    }
  };

  const reset = () => {
    setImage(null);
    desc.current.value = "";
  };

  const handleSubmit = async (e) => {
    e.preventDefault();

    const newPost = {
      userId: user._id,
      desc: desc.current.value,
    };

    if (image) {
      const data = new FormData();
      const filename = Date.now() + image.name;
      data.append("name", filename);
      data.append("file", image);
      newPost.image = filename;

      console.log(newPost);

      try {
        dispatch(uploadImage(data));
      } catch (error) {
        console.log(error);
      }
    }

    dispatch(uploadPost(newPost));
    reset();
  };

  return (
    <div>
      <div className="PostShare">
        <img src={ProfileImage} alt="" />
        <div>
          <input
            ref={desc}
            required
            type="text"
            placeholder="What's happening"
          />
          <div className="postOptions">
            <div
              className="option"
              style={{ color: "var(--photo)" }}
              onClick={() => imageRef.current.click()}
            >
              <UilScenery />
              Photo
            </div>

            <div className="option" style={{ color: "var(--video" }}>
              <UilPlayCircle />
              Video
            </div>

            <div className="option" style={{ color: "var(--location)" }}>
              <UilLocationPoint />
              Location
            </div>

            <div className="option" style={{ color: "var(--shedule)" }}>
              <UilSchedule />
              Schedule
            </div>

            <button
              className="button ps-button"
              onClick={handleSubmit}
              disabled={loading}
            >
              {loading ? "Uploading..." : "Share"}
            </button>
            <div style={{ display: "none" }}>
              <input
                type="file"
                name="myImage"
                ref={imageRef}
                onChange={onImageChange}
              />
            </div>
          </div>
          {image && (
            <div className="previewImage">
              <UilTimes onClick={() => setImage(null)} />
              <img src={URL.createObjectURL(image)} alt="" />
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

export default PostShare;

如果有帮助的话,我很乐意提供任何其他细节。

更新代码的其他部分:

RETRIEVING_SUCCESS调度程序:

import * as PostApi from '../api/PostRequest';

export const getTimelinePosts = (id) => async (dispatch) => {
  dispatch({ type: 'RETRIEVING_START' });

  try {
    const { data } = await PostApi.getTimelinePosts(id);
    dispatch({ type: 'RETRIEVING_SUCCESS', data: data });
  } catch (error) {
    dispatch({ type: 'RETRIEVING_FAIL' });
    console.log(error);
  }
};

getTimelinePosts用法:

import React, { useEffect } from 'react';
import './Posts.css';
import { PostsData } from '../../Data/PostsData';
import { useDispatch, useSelector } from 'react-redux';
import { getTimelinePosts } from '../../actions/postAction';
import Post from '../Post/Post';

const Posts = () => {
  const dispatch = useDispatch();
  const { user } = useSelector((state) => state.authReducer.authData);
  let { posts, loading } = useSelector((state) => state.postReducer);

  console.log('posts content', posts);

  useEffect(() => {
    dispatch(getTimelinePosts(user._id));
  }, []);

  return (
    <div className="Posts">
      {/* {posts.map((post, id) => {
        return <Post data={post} id={id}></Post>;
      })} */}
    </div>
  );
};

export default Posts;
5gfr0r5j

5gfr0r5j1#

在postReducer中,让我们删除switch语句上的默认值,我们不需要reducer上的默认值,因为其他操作将在此处执行,并且代码使所有状态返回初始状态。

mmvthczy

mmvthczy2#

好的,我找到了一个解决posts数组中null项的方法。虽然我不知道为什么会这样,但它只会将实际的posts附加到posts数组中,而不会输入null。我所要做的就是改变reducer更新状态的方式。我最初使用immer,但现在不再使用了。下面是代码:

const postReducer = (
  state = { posts: [], loading: false, error: false, uploading: false },
  action
) => {
  switch (action.type) {
    case 'UPLOAD_START':
      return { ...state, uploading: true, error: false };
    case 'UPLOAD_SUCCESS':
      return {
        ...state,
        posts: [action.data, ...state.posts],
        uploading: false,
        error: false,
      };
    case 'UPLOAD_FAIL':
      return { ...state, uploading: false, error: true };
    default:
      return state;
  }
};

相关问题