foreword
The matter originated from a communication with the CTO. At that time, due to the nervousness and the long time to deal with these bugs, the answer was a mess at that time, so I thought of reorganizing the questions answered at that time, clarifying the reasons for the problems, and doing Kung fu in peacetime, while deepening memory.
A total of two things were said:
1. 翻页问题的异常。
2. SSR 与 CSR 界限的区分。
general reason
A major premise for these problems is that server-side rendering (SSR) is used in the project, so it is necessary to distinguish between SSR rendering and CSR rendering. Also because the SSR project has not been dealt with before, some components and business processing ideas in the early stage are still in the CSR model, resulting in a series of problems.
Exception for pagination issues
bug description
The project has been online for a long time, and suddenly there is user feedback. When the browser back button rewinds the page, the route has been reverted successfully, but the page data is still the current data.
BUG analysis
The paging components are uniformly packaged, so let's see what's going on! Look at the code first
const clickPage = (page) => { if (callBack && typeof callBack === 'function') { // 这个方法是去请求分页的数据 callBack(page); } if (pathName.includes('?')) { history.push(`${pathName}&page=${page}`); } else { history.push(`${pathName}?page=${page}`); } }; <Pagination.Item href={href} onClick={(e) => { e.preventDefault(); clickPage(); }} > 页码 </Pagination.Item>
An example of a page number is given above,
Pagination.Item
will be rendered asa
tag, so we can determine the cause of this problem from here, we first go to get the currently clicked page data, and then go to the jump page.
When I saw this, I was stunned, how could there be such a strange operation? Shouldn't paging jump to the page first, then monitor the page's changes in the page, and request data? Why do you have to deal with it this way?
This goes back to the big reason mentioned above. SSR and CSR loading scenarios need to be distinguished. Why do we need to distinguish? Because if all modes go to SSR, the pressure on the server will be great, so some user click operations such as page turning, sorting, etc., these operations can use the CSR mode, so I was writing some public components (paging, Sorting), it is written in this way:
- Reserving the address on the pagination is beneficial to search engine indexing and SEO, and then actually uses the client-side jump method to change the route to get the data before the jump.
- This ensures that it must be rendered in a CSR manner, without having to distinguish the influence of SSR.
Therefore, based on the above two reasons, this method is adopted. In fact, this set of logic can be used completely without considering the method of browser fallback (low frequency operation). This is also the reason why this bug was not found at the beginning. .
BUG solution
Since the BUG is caused by the above two 'advantages', then prescribe the right medicine.
- It is necessary to monitor the changes of the route and then obtain the data according to the corresponding parameters.
- Make sure that the SSR and CSR do not affect each other, otherwise the server side renders the client side and executes it again, which is too waste of resources and the loading effect will also be affected.
To modify according to this idea, first remove all incoming callback functions, and let the component just complete the routing jump. After sorting it out, I found a benefit, avoiding the layer-by-layer incoming of callback functions, and removing a lot of redundant Code, the only thing that needs to be adjusted and thought is how to distinguish SSR from CSR (more on that later).
// 调整后的代码 大致
// 组件
const clickPage = (page) => {
if (pathName.includes('?')) {
history.push(`${pathName}&page=${page}`);
} else {
history.push(`${pathName}?page=${page}`);
}
};
<Pagination.Item
href={href}
onClick={(e) => {
e.preventDefault();
clickPage();
}}
>
页码
</Pagination.Item>
// 页面内
useEffect(()=> {
// 次数省略了区分服务端跟客户端渲染的条件
loadDataByPage(page)
}, [page])
The distinction between SSR and CSR boundaries
This question is due to the thinking brought about by the above transformation. How to distinguish this condition? What is the best way to differentiate? In fact, up to now, I think it is only how to distinguish the conditions. There is no correct way of thinking for the time being if there is a better way.
thinking at the time
- Add a logo, and change the logo separately when SSR and CSR.
- Use the existing data conditions to distinguish, only need to save the routing parameters when saving the data.
For the first method, the advantages can strictly distinguish the two cases, but need to add additional fields. Moreover, the logo needs to be changed frequently, and each page needs to be added. Even if it is placed in the public data, each page needs to be referenced separately. The amount of engineering is relatively large, and the readability of the code will be poor, and the page logic, parameters Many times, there are many places to modify, which is prone to problems. After trying some pages, I chose to give up this method.
For the second method, you only need to add routing parameters when storing data. You only need to adjust the method of storing data. You do not need to adjust the reference in the page and the request method, but the trigger logic needs to be written more rigorously, otherwise it is easy to cause Repeated requests are a waste of resources.
Continue to take pagination as an example
// 将触发方法放在页面内,能够触发这里的一定是 CSR, 因为 SSR 请求不在这里触发
// 改造后 Query.page 路由携带的参数 dataPage页面存储的当前分页数据
useEffect(() => {
// 处理 pagenation 分页
// 增加这些条件判断 是为了防止 SSR 模式后 进入浏览器又触发一遍请求
if (Query.page && dataPage !== Number(Query.page)) {
loadDataByPage(Query.page);
}
if (dataPage > 1 && !Query?.page
) {
loadDataByPage(1);
}
}, [Query.page]);
Modifying a bug where the data of the browser back page is incorrect has been resolved. The causes and consequences of these things have been explained clearly, and I can make up for the regret and regret that I didn't say last time.
You may not feel very complicated logic just by looking at the examples here, but if one of the conditions changes, it really only takes so long to modify a single list page, but we have a very complex page (personal home page) , routing combination, additional paging, filtering conditions, etc. There are dozens of changes. To deal with these conditions, it needs to be carefully distinguished, which is also quite complicated, and when dealing with these conditions, try to choose a single condition for single processing, avoid Relying on multiple conditions at the same time, otherwise it will cause additional influencing factors, which are debugged bit by bit.
end
Thinking and accumulating more on a daily basis and avoiding cramming will prevent you from getting stuck at critical moments, and your mental quality needs to be strengthened. Why is it so tense just for an ordinary conversation? It's not too late to make up for it. You must make up for your own deficiencies in a timely manner. Come on and hire workers! ! !
Off topic
Most programmers are actually dealing with business, how to reflect value from business? Or how to show the highlights of the business when reporting? When you feel that the business you are dealing with has no bright spots, what should you say? Suggestions and discussions are welcome!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。