在 react-redux 应用程序中更新部分状态时,整个页面闪烁并跳转到顶部

Posted

技术标签:

【中文标题】在 react-redux 应用程序中更新部分状态时,整个页面闪烁并跳转到顶部【英文标题】:Whole page is flickered and jump to top when a part of the state is updated in react-redux application 【发布时间】:2019-11-22 00:23:57 【问题描述】:

在我的 react-redux 应用程序中,我可以通过一个界面正确更新一些数据,如下面的 gif 所示。下面是改变redux状态的对应代码:

case UPDATE_COMMENT_SUCCESS:
        const commentUpdated = action.payload.normalizedData;
        return 
            ...state,
            loading: false,
            editing: false,            
            discussionPosts: 
                ...state.discussionPosts,
                [commentUpdated.id]: 
                    ...state.discussionPosts[commentUpdated.id],
                    content: commentUpdated.content
                
            
        ;

下面是点击按钮的onclick事件:

const onSubmit_updateComment = (event) => 
    event.preventDefault();
    props.updateComment(
        Id: st_activeCommentToEdit,
        Content: st_commentTextEdit,
        UserId: currentUserId
    );
    set_activeCommentToEdit('');

这是触发onSubmit_udatecomment 事件的表单:

 <form onSubmit=onSubmit_updateComment className="mt-2">
     <div className="form-group">
         <textarea
             defaultValue=props.comments[commentId].content
             value=st_commentTextEdit
             className="form-control"
             onChange=onChange_commentTextEdit
         />
     </div>

     <div className="float-right">
         <button className="btn btn-sm btn-info" type="submit">Update</button>&nbsp;
         <button
             className="btn btn-sm btn-light"
             type="reset" onClick=(e) =>  e.preventDefault(); set_activeCommentToEdit(0) >
             Cancel
         </button>
     </div>
     <div style= clear: 'both' ></div>
 </form>

下面是更新数据库的代码(即下面代码中的props.updateComment):

export function UpdateComment(commentData) 
    return dispatch => 

        dispatch(dataOperationBegin());

        axios(
            method: 'post',
            url: 'api/AssessmentDiscussionPost/Update',
            data: 
                Id: commentData.Id,
                Content: commentData.Content,
                PostOwnerId: commentData.PostOwnerId
            
        )
            .then(response => 
                console.log('success: Updated the comment');
                console.log(response.data);

                dispatch(updateCommentSuccess(response.data));

                toaster.notify('Comment is posted successfully.', 
                    duration: 2000
                )
            )
            .catch(error =>  dataOperationFailure(error) );
    ;

我尝试不使用toaster.notify,但同样的问题仍然存在。

这是第一次加载数据的主组件中的代码:

useEffect(() => 
    if (props.loading == false)//when the loading is complete
    
        props.fetchReviewAlignPerspectivesdCardData(submissionId);
    

, [submissionId])

这是 dispatch 到 props 的映射:

const mapDispatchToProps = (dispatch) => 
   return 
       fetchReviewAlignPerspectivesdCardData: (submissionId) => dispatch(FetchAlignPerspectivesData(submissionId)),
         

此外,使axios调用数据库的FetchAlignPerspectivesData函数如下:

export function FetchAlignPerspectivesData(submissionId) 
    var url = 'api/x/y';

    return dispatch => 

        dispatch(alignPerspectivesDataOperationBegin);

        axios.get(url,  params:  submissionId  )
            .then(response => 

                const alignPerspectives = new schema.Entity('alignPerspectives');
                const assessments = new schema.Entity('assessments');
                const discussionPosts = new schema.Entity('discussionPosts');
                const childPosts = new schema.Array(discussionPosts);
                discussionPosts.define(
                    childPosts: [childPosts]
                );

                alignPerspectives.define(
                    assessments: [assessments],
                    discussionPosts: [discussionPosts]
                );

                const normalizedData = normalize(response.data, alignPerspectives);
                dispatch(fetchAlignPerspectivesCardSuccess(normalizedData))
            )
            .catch(error =>  alignPerspectivesDataOperationFailure(error) );
    

我不认为fetchReviewAlignPerspectivesdCardData 是闪烁的原因(因为在更新字段时不会再次调用它)。我想知道这个问题可能是什么原因。有什么想法吗?

更新

好像`

export const DATAOPERATION_BEGIN = "DATAOPERATION_BEGIN";
export const dataOperationBegin = () => (
    type: DATAOPERATION_BEGIN
)

这是case DATAOPERATION_BEGIN的reducer代码,其中loading设置为true

 const alignPerspectivesReducer = (state = initialState, action) => 
     switch (action.type) 
         case DATAOPERATION_BEGIN:
             return  ...state, loading: true, error: null ;

我想知道我发送dataOperationBegin 的方式是否有问题。有任何想法吗?

【问题讨论】:

使用 chrome 中的 react 开发者工具,查看所有发生的事件 updateCommentSuccess 长什么样子? @Andrew 非常基础:export const updateCommentSuccess = (normalizedData) =&gt; ( type: UPDATE_COMMENT_SUCCESS, payload: normalizedData ) 请告诉我们按钮的onClick 处理程序触发了哪个函数。 这里没有足够的代码来重现。 minimal reproducible example 【参考方案1】:

如果没有完整的代码很难重现,但看起来你不小心提交了一个表单,这可以通过设置 &lt;button type="button"&gt;... 来解决(否则,默认情况下它将是一个提交按钮)或通过在表单上设置e.preventDefault

【讨论】:

以上是关于在 react-redux 应用程序中更新部分状态时,整个页面闪烁并跳转到顶部的主要内容,如果未能解决你的问题,请参考以下文章

根据 React-Redux 状态的动态页面不更新渲染数据

react-redux 使用小结

react-redux 使用小结

为啥初始状态没有保留在 react-redux 中

react-redux状态管理器

深入理解Redux之手写React-Redux