All of a sudden, there was a feedback from an overseas user, who said that a page would go blank if you click the “add” button. The other party could not speak Chinese, so the whole process of communication was in English, using the level 6 dumb English that I picked my feet. The communication process was a little more difficult. At the beginning of the white screen, there is no fluctuation in the heart, this kind of problem is nothing more than a certain interface data return is not scientific, and then the front end has no fault tolerance. Only need to see the error message can be resolved in seconds
The front row tips, nuggets now when the release of banned words will not be sent out. So I spent half an hour sending an article, repeatedly using dichotomy to exclude the location of prohibited words, can be sent to explain that the previous content is no problem, and then add a little content to continue to try. When I was still sending the article, I saw 200 browsed and apologized to 200 small friends. At that time, I was still trying sensitive words, the content of the article was not complete. Now it is good and I can look back. For example, “error” sometimes needs to be changed to “error”, pages cannot have emojis, and “jiechi” is prohibited (hijack later). It is highly recommended to give a list of banned words, or pop up a reminder when you detect a banned word
Let the user open the console
Let the user refresh and repeat, keeping the console state open. How to open the console to which panel, and then ask the other side to take a screenshot, the result is this error:
Cannot read property xx of undefined React source code setstate after dispatch, trigger batch update, execute scheduling error. React was suddenly overwhelmed when some other operation changed the DOM node. Even if I knew that, how would I know? Then directly to retrieve the interface data, put the local run to see if you can reproduce it
Instruct the user to send a response
After a bit of foot English communication and step screenshots, finally let the user send the relevant interface return data. I got the numbers. It’s my turn to perform. I start running dev locally and delegate all these interfaces to the data I just got
As a result, it worked perfectly and nothing happened
Then I try to see the other side of the screen recording, it turns out that there is no error operation, only click the button, and the react source code is the same error, the interface is normal. Finally, I decided to let the user scan my computer code and log in to my computer account
In my computer boarded the number of others, began a meal operation, came to the same page, click the button, the result is normal, what did not happen…… Do you have a lot of question marks
Remote desktop
Out of options, I video-called and asked for screen sharing. I got through and started the whole process of oral communication. I could only speak my spoken English slowly, and I guess the other party could barely understand it. I repeated the previous operation, sure enough, there again, came to the same page, click the button, immediately reported an error. It’s the same problem
So began to interrupt the point, the operation of a few, incredibly their own good! ??
Behind refresh the page, all natural good……..
Heart tired, temporarily no matter so much, nothing is good, things so far.
“looks fine for now. Thank you so much!”
Things come up again
A few days later, while happily writing requirements, I was suddenly pulled by the robot. It was the same person, the same question, but a different page link. Before you start, let’s get this straight:
- React source code error, there must be a native DOM operation outside react
- The code has been verified that there are no other native DOM operations
- They’re doing dom manipulation on the console, right? No way. No technical background
- It has to be browser plugins, man-in-the-middle injection (almost impossible with lowest priority), translations
- Forget about the last interruption. No cutting corners
Last time I learned that direct remote control is the best approach. And immediately connected to the remote control. Checked the browser plugins, nothing affected – browser plugin pass. Confirm whether the translation, asked the other party said whether open the translation, the other party said no (remote desktop can not see the pop-up menu, so I need someone to tell me)
Ok, they say there is no translator, so I assume that is true. Since the root cause of the problem is native DOM operations outside react, the dom node count is likely to be different. So I typed it on the console, okay? (‘*’) to find 2400 nodes on the other computer. If I type it on my computer, there are only 2000 nodes. Ask a colleague to help see, also 2000 nodes. So I decided to compare the first different node and typed a simple script on their computer console:
? (The '*').reduce((acc, { tagName }) = > `${acc}${tagName}, `.' ')
Copy the code
I: “Could you please copy the TXT and send me”
So I got all of the tag strings from the user’s entire page, and compared them to mine in the console of the page I opened:
var arr = otherHtml.split(', ')
?(The '*').findIndex(({ tagName }, i) = >tagName ! == arr[i])Copy the code
It was found that the index was 103 and the 103rd node was found to be a link tag which introduced a CSS at translate.googleapis.com and the HTML tag added a class called translated- LTR. As the name suggests, the translation is solid
Then, continue to expand the main content, found that the other side of the page many font tags!!
Sure enough, or open the translator, but people “feel not open”. In fact, it is likely that the previous set of uniform translation, so the back has been no matter, all websites will automatically translate. I then asked the user to turn off the translation as I asked. In the end, repeated operation, the problem did not appear
In fact, it is estimated that before everyone is scaffolding a brush, and did not notice the HTML lang value, and our system is English. So there is a “Chinese” page with all the content in English. The logic of overseas Chrome translation is that this is a “Chinese” page, which needs to be automatically translated, and then “English translated into English”. There is no visual change, in fact, dom nodes have a lot of font
<html lang="zh-cn">
Copy the code
Why was it okay the last time
So I wanted to see why the break point didn’t work last time, and open Wikipedia to see what happens to the break point with translation enabled. Open the Source panel and check the Load event
Automatic translation is also enabled
<html class="client-js" lang="en" dir="ltr">
Copy the code
When I clicked the next two steps, the HTML tags changed. The core features were: translated LTR
<html class="client-js translated-ltr ve-not-available" lang="zh-CN" dir="ltr">
Copy the code
Look again at the Element panel, which has a lot of font wrapping
- I have a breakpoint on the return of the last interface before the error occurs, and check the breakpoint of the error event
- A cORS error is reported and error is stuck. At this time, there is already a request out, and the break button buys time (you seem to be pending, but actually the response has already arrived at your door).
- Click the next step, the data in front of the second out, the moment again stuck, because the last interface also came back
- This is not the time to pull the translation resources, but the page is displayed completely. With a click of a button, I managed to get past the translation confusion. This is a create button, after the successful creation is the user’s own operation
- Because creation is a slightly less frequent activity, no feedback is received for several days
- The problem is usually when you delete an element after setState, that element can’t be traced back to an error. Clicking the button here does delete the button and switch the page
React: How do I react
React: How do you react
const { useState, useLayoutEffect } = React;
export default function App() {
useLayoutEffect((a)= > {
const font = document.createElement("font");
const app = document.querySelector(".App");
// Create the effect of font wrap, simulate the effect of translation, destroy the original structure
while (app.firstChild) {
font.appendChild(app.firstChild);
}
app.appendChild(font);
setTimeout((a)= > {
// set state
setShow(false);
}, 1000); } []);const [show, setShow] = useState(true);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
{show && (
<>
123123
<h2>Start editing to see some magic happen!</h2>
</>
)}
</div>
);
}
Copy the code
The desired effect occurred:
In fact, there is no need to manually change, you just need to right click on the translation for Chinese can reproduce. React stores parentNode in advance, so child nodes cannot be found
The solution
Error boundary component
React’s two life cycles are used to sense translation errors and then display a bottom-pocket UI that prompts the user to turn off the translation. The operation document link is also given. When using it, just wrap the component with TranslateErrorBoundary
class TranslateErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { translateError: false };
}
static getDerivedStateFromError() {
if (document.documentElement.classList.contains("translated-ltr")) {
return { translateError: true };
}
}
componentDidCatch(e, info) {
// A translation error is reported
report(e, info);
}
render() {
if (this.state.translateError) {
return (
<>
<strong>
translate error! you' d better to turn your google-translate off and reload. see
</strong>
<a
target="_blank"
rel="noopener noreferrer"
href="Document link"
>The document</a>
</>
);
}
return this.props.children;
}
}
// usage
<TranslateErrorBoundary>
<Cpn />
</TranslateErrorBoundary>
Copy the code
Do not have a text node in the outermost layer of a react element that can be deleted
Without further ado, see 🌰
<div className="App">
<h1>Hello CodeSandbox</h1>
{show && (
<>
123123
<h2>Start editing to see some magic happen!</h2>
</>
)}
</div>
Copy the code
This section has the outermost text node 123123, so the translation will error:
{show && (
<>
123123
<h2>Start editing to see some magic happen!</h2>
</>
)}
Copy the code
Why is that? Delete node “123123”, but its parent node can not find it any more
{show && (
<>
<font><font>123123</font></font>
<h2><font><font>Start editing to see some magic happen!</font></font></h2>
</>
)}
Copy the code
Corrective action: Add span tags and don’t make 123123 bare
{show && (
<>
<span>123123</span>
<h2>Start editing to see some magic happen!</h2>
</>} // after translation {show && (<>
<span><font><font>123123</font></font></span>
<h2><font><font>Start editing to see some magic happen!</font></font></h2>
</>)}Copy the code
Because the outermost element is a span, if you add a font, you add it inside a span. If you delete the element, you will find a span
Look at another 🌰
<div> {label ! == undefined ? ( <div> {label} </div> ) : null} {children} </div>Copy the code
In this case, label is plain text. After the example above, we know that {label} has a span. But there is a risk: if this component is used externally, and the externally is passed in by children, meaning that the content of children is variable, such as passing in a string, and setstate is followed by another node, then the problem arises again
The error condition is repeated: a block of the react element that can be deleted has text nodes in its outermost layer. At this point, children is a piece of element, and it is variable. The outermost node is the outermost node of the object children, and there is a text node that is a string, so the error condition is met
TextNode1 children is text node, for example, so normally after setstate if children changes, delete textNode1 way textNode1ParentNode. RemoveChild (textNode1). TextNode1 is no longer a child of textNode1ParentNode if it is translated and the text node wraps two layers of font. In addition, even if you change the outer div to span, section, or article, you will get an error
Corollary: Do not expose mutable text nodes directly under any element
All the code is written by myself, such as props. Children, such as props. Children, such as props. You can actually write a tool that scans the AST and automatically wraps a span with bare text nodes
Or, make a issue ask react there can not save to the parent node, delete elements directly when node. ParentNode. RemoveChild?
conclusion
- Frameworks that use data-driven views like React and Vue, if you encounter a source error, consider whether native DOM operations are being scrambled
- If you’re sure it’s not native DOM manipulation, consider browser plugins and translations
- You do need to use native operations in React and Vue. You need to take this risk into account
- If this problem occurs in international services, it is recommended to start troubleshooting from browser translation
- Don’t let a react element that can be deleted have text nodes at its outermost layer. Make sure there are mutable text nodes
Pure write demand write business boring? Let’s get together. Pay attention to the public account “Different front-end”, learn front-end from a different perspective, grow fast, play with the latest technology, explore all kinds of black technology