Issue 7: Nine tips for sharing inspiration
1. The derivation of the ts array type is inexplicably disturbed
The thing is like this, a small optimization needs to be done on Friday, a certain file originally exported three " json objects", I need to export three
function
to change the export content according to the parameters, and then it happened. Strange type error, suppose the following code is currently available:
The following code will not report an error and can run normally
export interface Dog {
name: string;
age?: 1 | 2 | 3;
}
export const a = (): Dog => ({
name: "金毛",
});
export const b = () => ({
name: "比熊",
age: 2,
});
export const c = () => ({
name: "拉布拉多",
});
const cc: Dog[] = [a(), b(), c()];
But the strange thing is that the following code will report an error
export interface Dog {
name: string;
age?: 1 | 2 | 3;
}
export const a = (): Dog => ({
name: "金毛",
});
export const b = () => ({
name: "比熊",
age: 2,
});
export const c = (): Dog => ({
name: "拉布拉多",
});
const cc: Dog[] = [a(), b(), c()];
I just specified the return value for the third method, and the second method reported an error. I did not specify the return value for the third method, but the third method did not report an error. Then there are strange phenomena, but I am When the third method is designated to return the any type, the second method does not report an error:
After research, it is found that when a value in the array is designated as any
, the array type will become any[]
, so c()
is designated as returning any without error.
When A and c two methods are designated as
Dog
time type, ts
found return value b of the method is not necessarily in line with
Dog
deduction, because Dog
type inside age
can only contain 1|2|3
so error, but if you do not completely Specifying the return value type for a b c
will not report an error, and ts will automatically deduce that 2 is within the range, which is amazing!
2. How to design a component of undefined | bl structure
For example, suppose that the tip prompt box component has a parameter
showTip
is a boolean value. When the value is true
, even if the user does not hover with the mouse, the pop-up box will appear, which is false
it shows.
At present, there is a requirement that after entering the page, this box will automatically pop up and stay 3s
then disappear.In fact, we can easily think of assigning showTip
to true
3 seconds and then changing to undefined
, because there are only two situations, either true or undefined. Just like the following code writing method:
const obj = {};
if(isFirstOpenPage){
obj.showTip = true;
}
return <tip {...obj}>
However, when I used a component library, it appeared that as long as the showTip
attribute was defined, it could not be set to undefined
. After I popped up tip
, I couldn't restore it to let the user control the display or hide.
This is actually a problem to be considered when designing the code. When we design an Boolean, we should also consider that
undefined
may also be a value passing situation.
Third, how does react refresh the component itself
The situation I encountered is that there are a, b, c
. These three components correspond to three different special situations. Each situation may appear, but only one of these three components can appear at the same time, such as the current one. a
components, the user clicked the close appear b
components, which leads to a time when the user clicks the close I want to determine whether the other two components need to be rendered.
The problem is that, for example, to remove the component, the component library method is to directly remove the dom structure of
, which causes the reaction to be unable to monitor.
const [_, forceUpdate] = useReducer(x => x + 1, 0);
if (showA) {
return <A forceUpdate={forceUpdate} />;
} else if (showB) {
return <B forceUpdate={forceUpdate} />;
} else if (showC) {
return <C forceUpdate={forceUpdate} />;
} else {
return null;
}
Inside each component
onClose={() => {
if (forceUpdate) {
forceUpdate();
}
}}
The key to the above method is that useReducer
can cause the component to be re-rendered.
Fourth, insert jsx elements for the string
The thing is like this, for example, currently we have a i18n copy of
highest price {max} - lowest price {min}
, the existing method can replace {max}
and {min}
by passing in two strings, but it can only be replaced with a string, and the dom structure cannot be inserted, for example, I want to use Replace with blue words.
Suppose intl
method may string inside replace {max}, we intl
be expanded into intlPlus
, following the usual manner is used.
intl.format(
"highest price {max} - lowest price {min}"
[
"99", "33"
]
)
The preparation of intlPlus
import intl from './intl';
const pix = '-------------';
export default function intlPlus(i18n: string, arg: any[]) {
const len = arg.length;
const box = Array(len).fill(pix);
const text = intl.format(i18n, box);
const textArr = text.split(pix);
const res: any[] = [];
for (let i = 0; i < textArr.length; i++) {
res.push(textArr[i]);
if (arg[i] !== undefined) {
res.push(arg[i]);
}
}
return res;
}
The above principle is to use '-------------';
as the station symbol, and then cut the placeholders in order, and then insert them in the form of one copy and one interpolation, and output them in the form of an array. The usage is as follows:
intl.format(
"highest price {max} - lowest price {min}"
[
"99", <span style={{color: red}}> 33 </span>
]
)
5. How to prevent the address of the test environment from leaking
For example, we usually test environment. For example, the following code will leak the code of the test domain name:
const pathObj = {
prod: 'www.xxxxxx.com',
dev: 'www.xxxxxxx-dev.com',
test: 'www.xxxxxx-test.com'
}
// ....
if(location.host === 'localhost:3000'){
window.open(pathObj.dev)
}
The plug-in webpack.DefinePlugin
✨, this plug-in allows us to set some "global" (quoted) variables, which can be used before the official
packaging:
plugins: [
new webpack.DefinePlugin({
isDev:
process.env.NODE_ENV === "production"
? JSON.stringify("false")
: JSON.stringify("true")
}),
]
The above weird use JSON.stringify
, because only in this webpack
can 0617616baa8bb9 treat it as a string, otherwise it will be treated as a statement. Next, let's take an example of use:
We observe the package file:
Observation shows that'oooooooo' no longer exists in the packaging file.
Its principle is to replace globally, such as the above code:
// 打包前:
if (isDev) {
console.log("tttttttttt");
} else {
console.log("ooooooooooo");
}
// 打包时:
if (false) {
console.log("tttttttttt");
} else {
console.log("ooooooooooo");
}
Obviously, tree-shaking
will not let this code go, so the following'ooooooo' logic will be deleted.
The point that this plug-in is a bit difficult to understand is that it is not executed at runtime, but a global replacement before tree-shaking
The reason why it can be written directly in the global isDev
, but not window.isDev
is because it is not mounted on the widnow object, and such variables will not run on the user side.
6. i18n translation does not take effect immediately after exporting as {}
There are many configurations that need to be changed in real time. It is best not to design in the form of json, such as the translation in the project. When the user switches the language from English to Chinese, it is found that the translation is still in English in some places. The characteristics of these places are all The exported json is similar to the following:
export UserName = {
title: <span> {i18n(USER_NAME_TITLE)} </span>
}
How to use
import {UserName} from './userName'
// ...
<Table
columns={[UserName]}
>
table header written in the above method does not change the text with the language switch.
Seven, the segmentation of item2 is easy to use
The command line tool can greatly alleviate the problem of our multi-project startup. If you vscode
provided by shell
, you will feel that it is a bit difficult to switch back and forth, and what is worse is that you develop more than two at the same time. micro-front-end project, so this
item2
, because this is so easy to use, friends who have not played like this can quickly play it:
Each click will add a small window, let's see how to divide the console into '6 parts':
To prevent confusion, we can name each window:
The setup process is as follows:
You can also set your favorite background pattern:
The setup process is as follows:
8. The tip prompt is bizarre and hidden
table in a pop-up box I am making. The header of one of the columns of this 0617616baa8f62 is in the pop-up state by default, but the bug I encountered is that the pop-up state will flash by sometimes and change back to
table
Status, after reading the source code of the component library, it is determined that it is not the problem of the component itself.
After many tests, it was found that this bug is related to the position of the button of the pop-up pop-up box. This made me want to understand the cause of the bug, because this pop-up box has a pop-up animation, which appears from small to large from the left, and this one becomes larger. In the process, the components in this bullet box have actually been pre-rendered, which causes the mouse to pass through the bullet box when it appears, which causes the component to think that the user has hovered, causing the tip to hide...
The solution is to disable the 300 millisecond mouse event when this bullet box appears.
9. Use Whistle to set up online domain names to develop local codes to prevent csrf defense
Because the server
side often adds some security policies, for example, only a certain referer
website can call api
, and other websites will report 403
. At this time, our poor front-end http://localhost:3000
has suffered, and we have to communicate with relevant personnel every time. Debugging problem.
Simply we can directly use the domain name of the test environment for development, without using http://localhost:
(similar to windows modifying the local host file) finally it works...
Step one: install Whistle
npm install -g whistle
w2 start -p 8899 // 启动服务
Open the domain name directly to see the operation interface: http://localhost:8899
Step 2: install proxy
Since we need to proxy all browser requests to Whistle, we need to use the Google plug-in proxy,
Search: Proxy SwitchyOmega
This step is to proxy the request of the browser to this address
Step 3: Configure Whistle
The front is the proxy address, and the space after the target address
There is currently such a page
After the agent
Step 6: Whistle configuration key certificate
Since Whistle wants to help us process all the requests, there are bound to be https requests, so we must import Whistle's certificate:
You're done, happily use the test environment domain name for local development of
.
end
This is the case, I hope to make progress with you.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。