7

Issue 7: Nine tips for sharing inspiration

image.png

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()];

image.png
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()];

image.png

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:
image.png

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

image.png
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:

image.png

We observe the package file:

image.png

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:
image.png

Each click will add a small window, let's see how to divide the console into '6 parts':

image.png

To prevent confusion, we can name each window:

image.png

The setup process is as follows:
image.png

image.png

You can also set your favorite background pattern:

image.png

The setup process is as follows:
image.png

image.png

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
image.png

Step 2: install proxy

Since we need to proxy all browser requests to Whistle, we need to use the Google plug-in proxy,

image.png

image.png

Search: Proxy SwitchyOmega

image.png

This step is to proxy the request of the browser to this address

image.png

Step 3: Configure Whistle

image.png

The front is the proxy address, and the space after the target address

image.png

There is currently such a page

image.png

After the agent

image.png

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:

image.png

image.png

image.png

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.


lulu_up
5.7k 声望6.9k 粉丝

自信自律, 终身学习, 创业者