【问题标题】:View is not updating after adding element to MongoDB向 MongoDB 添加元素后视图未更新
【发布时间】:2020-04-16 02:18:18
【问题描述】:

[已解决] 我正在尝试使用 Redux/React/Mongo/Typescript 制作一个小型应用程序,但遇到了一个问题,当我向数据库添加元素时,我可以在表中看到新添加的行,但其中没有值。但是刷新页面后,值就在那里。 我认为这是因为带有记录的数组会立即刷新,而新元素尚未在数据库中。我使用了等待/异步,但它没有解决这个问题。谁能帮我解决这个问题?

Action.ts

export const getAllTeams: ActionCreator<ThunkAction<Promise<any>, 
    ITeam[],                 
    null,                       
    ITeamGetAllAction          
    >> = () => {
    return async (dispatch: Dispatch) => {
        await axios.get('http://localhost:5000/teams/')
            .then(res => {
                    dispatch({
                        teams: res.data,
                        type: TeamActionsTypes.GET_ALL,
                    })
                }
            );
    };
};
export const addTeam: ActionCreator<ThunkAction<Promise<any>,
    ITeamAddTeamAction,
    ITeam,
    ITeamAddTeamAction         
    >> = (team: ITeam) => {
    return async (dispatch: Dispatch) => {
        await axios.post('http://localhost:5000/teams/add', team)
            .then(res => {
                dispatch({
                    type: TeamActionsTypes.ADD_TEAM,
                    result: res,
                });
            })
    };
};

Reducer.ts:

export const teamReducer: Reducer<ITeamState, TeamActions> = (
    state = initialTeamState,
    action,
) => {
    switch (action.type) {
        case TeamActionsTypes.GET_ALL: {
            return {
                ...state,
                teams: action.teams,
            };
        }
        case TeamActionsTypes.ADD_TEAM: {
            return{
                ...state,
                teams: [action.result,...state.teams]
            }
        }
        case TeamActionsTypes.GET_ONE: {
            return{
                ...state,
            }
        }
        default:
            return state;
    }
};

组件.tsx

interface RatingTableProps {
    getTeams: () => Promise<TeamActionsTypes.GET_ALL>;
    teams: ITeam[];
}

const RatingTable: React.FC<RatingTableProps> = ({
    getTeams,
    teams
}) => {
    useEffect(()=>{
        getTeams();
    },[]);

    return (
        <table className="striped">
            <thead>
            <tr>
                <th>Team</th>
                <th className="right-align">Clicks</th>
            </tr>
            </thead>
            <tbody>
            {teams && teams.map(team => {
                return <>
                    <tr key={team.name}>
                        <td>{team.name}</td>
                        <td className="right-align">{team.count}</td>
                    </tr>
                </>
            })}
            </tbody>
        </table>
    )
};

const mapStateToProps = (store: IAppState) => {
    return {
        teams: store.teamState.teams,
    };
};

const mapDispatchToProps = (dispatch: ThunkDispatch<any, any, AnyAction>) => {
    return {
        getTeams: () => dispatch(getAllTeams()),
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(RatingTable);

ComponentAdd.tsx

interface RatingFormProps{
    addTeam: (team: ITeam) => Promise<TeamActionsTypes.ADD_TEAM>;
}

const RatingForm: React.FC<RatingFormProps> = ({
    addTeam
})=> {
    const [teamName, setTeamName] = useState<string>('');

    const changeHandle = (event: React.ChangeEvent<HTMLInputElement>) => {
        setTeamName(event.target.value);
    };

    const handleSubmit = (event: React.FormEvent) =>{
        event.preventDefault();
        addTeam({
            name: teamName,
            count: 0,
        });
        setTeamName('')
    };

    return (
        <div className="row">
            <form onSubmit={handleSubmit}>
                <div className="inputField col s6">
                    <label htmlFor="teamName" className="active">
                        Name your team:
                    </label>
                    <input
                        onChange={changeHandle}
                        value={teamName}
                        type="text"
                        id="teamName"
                        placeholder="Best team name ever"
                    />
                </div>
                <div className="col s6">
                    <button className="btn-large waves-effect waves-light" type="submit" name="action">Submit
                    </button>
                </div>
            </form>
        </div>
    )

};
const mapDispatchToProps = (dispatch: ThunkDispatch<any, any, AnyAction>) => {
    return {
        addTeam: (team: ITeam) => dispatch(addTeam(team)),
    };
};

export default connect(
    null,
    mapDispatchToProps,
)(RatingForm);

teams.js(路由)

router.route('/').get(async (req, res) => {
    await Team.find()
        .then(teams => res.json(teams))
        .catch(err => res.status(400).json('Error: ' + err));
});

router.route('/add').post(async (req, res) => {
    const name = req.body.name;
    const count = 0;
    const newTeam = new Team({name, count,});
    await newTeam.save()
        .then(() => res.json('Team added to database!'))
        .catch(err => res.status(400).json('Error: ' + err));

});

它在 UI 中的外观: before adding new element after adding new element

如果您需要任何其他信息或代码,请告诉我。谢谢!

更新 1: 感谢评论,当然一个大错误是发布后返回实际对象,而不是字符串(我感到羞耻)

router.route('/add').post(async (req, res) => {
    const name = req.body.name;
    const count = 0;
    const newTeam = new Team({name, count,});
    await newTeam.save()
        .then((team) => res.json(team))
        .catch(err => res.status(400).json('Error: ' + err));

});

更新 2: 天哪,这是一个愚蠢的错误 之前的更新解决了一个问题,但是在我从 dipatch 收到未定义的值之后,这是因为我返回的是 Promis,而不是值。

export const addTeam: ActionCreator<ThunkAction<Promise<any>,
    ITeamAddTeamAction,
    ITeam,
    ITeamAddTeamAction         
    >> = (team: ITeam) => {
    return async (dispatch: Dispatch) => {
        await axios.post('http://localhost:5000/teams/add', team)
            .then(res => {
                dispatch({
                    type: TeamActionsTypes.ADD_TEAM,
                    result: res.data, //<- Instead of just res
                });
            })
    };
};

感谢大家,他们花了一些时间,一如既往的愚蠢错误。

【问题讨论】:

    标签: reactjs mongodb typescript mongoose redux


    【解决方案1】:

    您应该从后端 API 返回更新后的 team。您可以像这样修改您的 API。

    router.route('/add').post(async (req, res) => {
        const name = req.body.name;
        const count = 0;
        const newTeam = new Team({name, count,});
        await newTeam.save()
            .then(team => res.json(team))
            .catch(err => res.status(400).json('Error: ' + err));
    
    });
    

    如果问题仍然存在,请发表评论。

    【讨论】:

    • 是的,我也发现了这个问题,非常感谢,但是视图中仍然没有显示,只是一个空白行
    • 我会把它标记为正确答案,因为它确实解决了问题,再次感谢您!
    • 你应该尝试添加一个像componentWillReceiveProps 这样的生命周期方法来改变你从redux store收到的props。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    • 2018-01-06
    • 1970-01-01
    • 2019-12-20
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多