向 MongoDB 添加元素后视图未更新

Posted

技术标签:

【中文标题】向 MongoDB 添加元素后视图未更新【英文标题】:View is not updating after adding element to 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
                );
            )
    ;
;

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

【问题讨论】:

【参考方案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。

以上是关于向 MongoDB 添加元素后视图未更新的主要内容,如果未能解决你的问题,请参考以下文章

mongoDB,mongoose,没有数组就添加,如果有了数组,就向数组中添加新元素

向表格视图控制器添加隐藏元素

当我向列表视图添加元素时,如何在 Flutter 中更新列表视图?

向数据表添加超链接时遇到问题

Appcelerator:元素未添加到android中的视图中

无法向(猫鼬)对象添加其他元素