Why using renderMessage in react-native-gifted-chat removes my Avatar?

I have a react native app, with react-native-gifted-chat. I wanted to change my fontFamily in all places so I changed it in the renderComposer and renderMessage props. After adding the renderMessage prop to my GiftedChat component my Avatars dissapeared. I tried to bring it back with the renderAvatar, but it does not work…

How can I have custom fonts and custom Avatars at the same time?

<GiftedChat
    messages={messages}
    onSend={onSend}
    user={{
    _id: 1,
    avatar: USER_AVATAR,
    name: USER_ID
    }}
    
    //Custom styles
    dateFormat="YYYY/MM/DD"
    timeFormat="HH:mm"
    renderInputToolbar={props => customtInputToolbar(props)}
    renderSystemMessage={props => customSystemMessage(props)}
    renderSend={props => customSendButton(props)}
    renderComposer={props => customComposer(props)}
    renderMessage={props => customMessageBubble(props)}
    renderAvatar={(props) => <Avatar {...props} />}
/>

...my styles...

export const customMessageBubble = props => {
    const renderMessageText=(props)=>{
        return (
            <>
            <MessageText
                {...props}
                textStyle={{
                right:{
                    fontFamily:'QuicksandMedium'
                },
                left:{
                    fontFamily:'QuicksandMedium'
                }
                }}
            />
            </>
        )
    }

    return(
        <Bubble 
        {...props}
        renderMessageText={renderMessageText}
        />
    )
}

export const customComposer = props => {
    return(
        <Composer 
        {...props} 
        placeholder={'Aa'}
        textInputStyle={{
            fontFamily:'QuicksandMedium',
        }}
        />
    )
}

enter image description here

Objects passed by reference

What exactly is happening here at the line( param = [1]) when passing the data, that the output is 0? If I switch the lines inside the function I get [0,2].

const  data = [0];

function changeData(param) {
  param = [1]
  param.push(2);

}
changeData(data);

Webpack bundling emits “require” statements in the distribution file

I have a TypeScript project, and I use Webpack to bundle the code to single JavaScript file. I’m using ESM only. When I try to run the distribution file by running: node ./dist/index.js I get this error:

const external_minimist_namespaceObject = require("minimist");
                                          ^

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and 'package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

Indeed, I configured "type": "module" in the package.json file.
I have this script to run the Webpack: "dist": "node --loader ts-node/esm node_modules/webpack-cli/bin/cli.js -c ./webpack.config.ts", in my package.json file.

This is my webpack.config.ts file:

import path from 'node:path';
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';

import webpack from 'webpack';
import nodeExternals from 'webpack-node-externals';
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
import WebpackShellPluginNext from 'webpack-shell-plugin-next';

const packageJsonData = await fs.readFile('package.json', 'utf-8');
const packageJsonObject = JSON.parse(packageJsonData);
const version = packageJsonObject.version;

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const configuration: webpack.Configuration = {
    context: __dirname,
    mode: 'production',
    target: 'node',
    entry: './src/index.ts',
    // * https://stackoverflow.com/questions/48673408/should-javascript-npm-packages-be-minified
    optimization: { minimize: false },
    externals: [nodeExternals({ modulesDir: path.join(__dirname, 'node_modules') })],
    experiments: { outputModule: true },
    module: {
        rules: [
            {
                test: /.ts$/,
                use: [
                    {
                        loader: 'ts-loader',
                        options: { configFile: 'tsconfig.build.json' },
                    },
                ],
                exclude: /node_modules/,
            },
        ],
    },
    plugins: [
        new WebpackShellPluginNext({
            onBuildStart: {
                scripts: ['rimraf dist'],
                blocking: true,
            },
            safe: true,
        }),
        new webpack.DefinePlugin({
            __PACKAGE_VERSION__: JSON.stringify(version),
        }),
    ],
    resolve: {
        extensions: ['.ts'],
        plugins: [
            new TsconfigPathsPlugin({
                configFile: './tsconfig.base.json',
                extensions: ['.ts'],
            }),
        ],
    },
    output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist'),
        library: { type: 'module' },
        chunkFormat: 'module',
    },
};

export default configuration;

And this is my tsconfig.base.json file which is the important one:

{
    "extends": "./tsconfig.paths.json",
    "compilerOptions": {
        "target": "ES2018",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "noEmit": true,
        "baseUrl": "./",
        "allowJs": false,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "esModuleInterop": true,
        "resolveJsonModule": true,
        "isolatedModules": true,
        "incremental": true,
        "removeComments": true,
        "allowUnreachableCode": false,
        "allowUnusedLabels": false,
        "alwaysStrict": true,
        "noFallthroughCasesInSwitch": true,
        "noImplicitAny": true,
        "noImplicitOverride": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noPropertyAccessFromIndexSignature": true,
        "noUncheckedIndexedAccess": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "typeRoots": ["./node_modules/@types", "./@types"]
    }
}

Webpack completes successfully, but I cannot run the distribution file with NodeJS. Why does the distribution file contain require statements instead of import to successfully run with ESM?

Internal Server error (500) in POST to MongoDB react

I am making a form that must POST to the Mongo database.

So I have the following code to make the change of the states in the Front:

const [project, setProject] = useState({
    project_start: null,
    project_end: null,
    project_name: "",
    usersId: [],
    partnerId: "",
    categoryId: "",
  });

  const handleChange = (name, newVal) => {
    setProject({ ...project, [name]: newVal });
  };

and the POST looks like this:

const handleSubmit = async (e) => {
    e.preventDefault();

    const res = await fetch("http://localhost:5001/client/projects", {
      method: "POST",
      body: JSON.stringify(project),
      headers: { "Content-Type": "application/json" },
    });

    const data = await res.json(project);
    console.log(data);
    console.log(project);
  };

And this would be a summary of what my form consists of:

<form onSubmit={handleSubmit}>
<Box width="50%">
                <LocalizationProvider dateAdapter={AdapterDayjs}>
                  <DatePicker
                    id="project_start"
                    name="project_start"
                    value={project.project_start}
                    onChange={handleChange.bind(null, "project_start")}
                    slotProps={{
                      textField: {
                        size: "small",
                        margin: "dense",
                      },
                    }}
                  />
                </LocalizationProvider>
                <TextField
                  id="nombreP"
                  name="project_name"
                  value={project.project_name}
                  onChange={handleChange}
                  margin="dense"
                  size="small"
                />
                <FormControl size="small" sx={{ m: 1 }}>
                  <Select
                    id="encargadoP"
                    multiple
                    name="usersId"
                    value={project.usersId}
                    onChange={(e) =>
                      handleChange(
                        "usersId",
                        typeof e.target.value === "string"
                          ? e.target.value.split(",")
                          : e.target.value
                      )
                    }
                    MenuProps={MenuProps}
                    renderValue={(selected) => (
                      <Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
                        {selected.map((value) => (
                          <Chip key={value} label={value} />
                        ))}
                      </Box>
                    )}
                    sx={{ width: 205 }}
                  >
                    {data?.map(({ _id, name }) => (
                      <MenuItem key={_id} value={name}>
                        {name}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              </Box>
            </Box>
            <Button
              type="submit"
              variant={"outlined"}
              size={"large"}
              sx={{
                width: 420,
                border: "1px solid white",
                m: "3rem 0 0 0",
                color: "white",
                borderRadius: "30px",
              }}
            >
              Agregar proyecto
            </Button>
          </Box>
        </form>

Here is my schema

import mongoose from "mongoose";

const ProjectSchema = new mongoose.Schema(
  {
    project_start: Date,
    project_end: Date,
    project_name: {
      type: String,
      required: true,
      min: 2,
      max: 100,
    },
    usersId: {
      type: [mongoose.Types.ObjectId],
      of: Number,
    },
    partnerId: {
      type: [mongoose.Types.ObjectId],
      of: Number,
    },
    categoryId: {
      type: [mongoose.Types.ObjectId],
      of: Number,
    },
  },
  { timestamps: true }
);

const Project = mongoose.model("Project", ProjectSchema);
export default Project;

In the Routes I have this:

import express from "express";
import {
  getAllUsers,
  getPartner,
  getCategory,
  addProject,
} from "../controllers/client.js";

const router = express.Router();

router.get("/users", getAllUsers);
router.get("/partners", getPartner);
router.get("/categories", getCategory);
router.post("/projects", addProject);

export default router;

In the controller this (in short):

import Project from "../models/Projects.js";
export const addProject = async (req, res) => {
  try {
    const {
      project_start,
      project_end,
      project_name,
      usersId,
      partnerId,
      categoryId,
    } = req.body;

    const newProject = new Project({
      project_start,
      project_end,
      project_name,
      usersId,
      partnerId,
      categoryId,
    });
    const savedProjecct = await newProject.save();
    res.status(201).json(savedProjecct);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
};

At the moment I get a 500 error when making the POST, I guess it is because of the schema I made with Mongoose, my questions are:

  • Is that the problem?
  • How can I take the id of the user, partner and category instead of the string (name) shown in the front end?

I am very grateful to people who can help me 🙂

Vite build.sourcemap hidden not loading in Chrome or Firefox

Migrating my react app from create-react-app to Vite and seeing some unexpected behavior with source maps. Vite docs regarding source maps are here. I was leaning toward using sourcemap: true until I saw that sourcemap: 'hidden' is the same thing except it is supposed to hide my comments … sounds like exactly what I want.

If I create a build with sourcemap: true, each JS file gets its own map file, and the JS file gets a comment like //# sourceMappingURL=mylibrary-033b4774.js.map appended at the end of it. The source maps get loaded into Chrome and Firefox as expected.

If I create a build with sourcemap: 'hidden', the only difference in output is that the //# sourceMappingURL=mylibrary-033b4774.js.map comment is NOT appended at the end of the JS file. A map file is still produced for each JS file, and it is accessible if I try to access it manually in the browser by typing its full path. However, the browsers don’t seem to like this … they don’t show the map at all.

Is this a bug in Vite or am I doing something wrong here?

Dynamic keys in typescript and javascript syntax

// Makes `function.name` return given name

function nameFunction(name: string, body: (args?: any[]) => any) {
    return {
        [name](...args: any[]) {
            return body(...args);
        }
    }[name];
}

In javascript I can do dynamic keys with such syntax:

let key = "jk_96";
let o = {
   [key]: ()=>{ console.log('Yup');} 
}

How is allowed in typescript to skip : after key name, and what [name] after closing brace of objects means?

Random element not working in play again button

This is a Higher or Lower game where the user guesses which driver has higher or lower stat depending on the difficulty. The play again button is the problem. What I want is when the user presses the play again button when the game ends it should pick 2 random drivers but not the same two drivers from the last game like my code does. I guess this is just a small problem but I’m not seeing what’s wrong.

// Define F1 driver data
const f1Drivers = [
      {
        name: 'Lewis Hamilton',
        wins: 103,
        podiums: 192,
        points: 4443.5
      },
      {
        name: 'Michael Schumacher',
        wins: 91,
        podiums: 155,
        points: 1566
      },
      {
        name: 'Sebastian Vettel',
        wins: 53,
        podiums: 122,
        points: 3098
      },
      {
        name: 'Alain Prost',
        wins: 51,
        podiums: 106,
        points: 798.5
      },
      {
        name: 'Ayrton Senna',
        wins: 41,
        podiums: 80,
        points: 614
      },
      {
        name: 'Nigel Mansell',
        wins: 31,
        podiums: 59,
        points: 482
      },
      {
        name: 'Jim Clark',
        wins: 25,
        podiums: 32,
        points: 274.5
      },
      {
        name: 'Juan Manuel Fangio',
        wins: 24,
        podiums: 35,
        points: 277.64
      },
      {
        name: 'Niki Lauda',
        wins: 25,
        podiums: 54,
        points: 420.5
      },
      {
        name: 'Jack Brabham',
        wins: 14,
        podiums: 31,
        points: 261
      },
      {
        name: 'Fernando Alonso',
        wins: 32,
        podiums: 101,
        points: 2106
      },
      {
        name: 'Max Verstappen',
        wins: 37,
        podiums: 80,
        points: 2080.5
      },
      {
        name: 'Nico Rosberg',
        wins: 23,
        podiums: 57,
        points: 1594.5
      },
      {
        name: 'Kimi Raikkonen',
        wins: 21,
        podiums: 103,
        points: 1873
      },
      {
        name: 'Mika Hakkinen',
        wins: 20,
        podiums: 51,
        points: 420
      },
      {
        name: 'Jenson Button',
        wins: 15,
        podiums: 50,
        points: 1235
      },
      {
        name: 'Jackie Stewart',
        wins: 27,
        podiums: 43,
        points: 359
      },
      {
        name: 'Damon Hill',
        wins: 22,
        podiums: 42,
        points: 360
      },
      {
        name: 'Felipe Massa',
        wins: 11,
        podiums: 41,
        points: 1167
      },
      {
        name: 'Valtteri Bottas',
        wins: 10,
        podiums: 67,
        points: 1791
      },
      {
        name: 'Mark Webber',
        wins: 9,
        podiums: 50,
        points: 1235
      },
      {
        name: 'Daniel Ricciardo',
        wins: 8,
        podiums: 32,
        points: 1311
      },
      {
        name: 'Charles Leclerc',
        wins: 5,
        podiums: 24,
        points: 874
      },
      {
        name: 'Sergio Perez',
        wins: 5,
        podiums: 28,
        points: 1255
      },
    ];
    
    // Get HTML elements
    const difficultySelect = document.getElementById('difficulty-select');
    const startGameButton = document.querySelector('button');
    const gameContainer = document.getElementById('game-container');
    const higherButton = document.getElementById('higher-button');
    const lowerButton = document.getElementById('lower-button');
    const resultContainer = document.getElementById('result-container');
    const playAgainButton = document.getElementById('play-again-button');
    const frontImage = document.getElementById('bikar');
    const easy = document.getElementById('easy_level');
    const normal = document.getElementById('normal_level');
    const hard = document.getElementById('hard_level');
    const diff = document.getElementById('diff-text');

    
    
    let currentDriverIndex;
    let previousDriverIndex;
    let currentDifficulty;
    let score;
    
    
    // Add event listener to the "Start Game" button
    startGameButton.addEventListener('click', startGame);
    
    function startGame() {
        startGameButton.style.display = 'none'
        frontImage.style.display = 'none';
        easy.style.display = 'none';
        normal.style.display = 'none';
        hard.style.display = 'none';
        difficultySelect.style.display = 'none'
        diff.style.display = 'none'


      currentDifficulty = difficultySelect.value;
      
      // Show the type of data to be guessed by the user
      const dataTypeElement = document.getElementById('data-type');
        if (currentDifficulty === 'easy') {
        dataTypeElement.textContent = 'Guess the driver with more wins';
      } else if (currentDifficulty === 'normal') {
        dataTypeElement.textContent = 'Guess the driver with more podiums';
      } else if (currentDifficulty === 'hard') {
        dataTypeElement.textContent = 'Guess the driver with more points';
      }
    
      higherButton.addEventListener('click', onHigherButtonClicked);
      lowerButton.addEventListener('click', onLowerButtonClicked);
      
      score = 0;
    
      // Hide the result container and play again button
      resultContainer.textContent = '';
      playAgainButton.style.display = 'none';
    
      // Show the first driver
      showNextDriver();
    }
    
    
    function onHigherButtonClicked() {
      checkAnswer('higher');
    }
    
    function onLowerButtonClicked() {
      checkAnswer('lower');
    }
    
    let lastDriverIndex;
    
    function showNextDriver() {
      // Clear the previous driver's data
      gameContainer.innerHTML = '';
    
      // Pick two random drivers from the list
      if (!currentDriverIndex) {
        currentDriverIndex = getRandomDriverIndex();
      }
    
      if (!previousDriverIndex) {
        previousDriverIndex = getRandomDriverIndex(currentDriverIndex);
      }
    
      // Create and append elements to display the two drivers and their data
      const currentDriverElement = document.createElement('div');
      const previousDriverElement = document.createElement('div');
      const currentDriverDataElement = document.createElement('ul');
      const previousDriverDataElement = document.createElement('ul');
      const vsElement = document.createElement('div');
    
      currentDriverElement.classList.add('driver');
      previousDriverElement.classList.add('driver');
      vsElement.textContent = "Vs";
    
      currentDriverElement.innerHTML = `
          <h2>${f1Drivers[currentDriverIndex].name}</h2>
          <img src="driver-images/${f1Drivers[currentDriverIndex].name.toLowerCase().replace(' ', '-')}.png">
        `;
      previousDriverElement.innerHTML = `
          <h2>${f1Drivers[previousDriverIndex].name}</h2>
          <img src="driver-images/${f1Drivers[previousDriverIndex].name.toLowerCase().replace(' ', '-')}.png">
        `;
    
      currentDriverElement.appendChild(currentDriverDataElement);
      previousDriverElement.appendChild(previousDriverDataElement);
      gameContainer.appendChild(currentDriverElement);
      gameContainer.appendChild(vsElement);
      gameContainer.appendChild(previousDriverElement);
    
      // Show the "Higher or Lower" buttons
      const buttonContainer = document.getElementById('button-container');
      buttonContainer.style.display = 'block';
    }
    
    function getRandomDriverIndex(excludeIndex) {
      let index;
      do {
        index = Math.floor(Math.random() * f1Drivers.length);
      } while (index === excludeIndex);
      return index;
    }
    
    
    function checkAnswer(guess) {
      const previousDriver = f1Drivers[previousDriverIndex];
      const currentDriver = f1Drivers[currentDriverIndex];
      let previousData, currentData;
      if (currentDifficulty === 'easy') {
        previousData = previousDriver.wins;
        currentData = currentDriver.wins;
      } else if (currentDifficulty === 'normal') {
        previousData = previousDriver.podiums;
        currentData = currentDriver.podiums;
      } else if (currentDifficulty === 'hard') {
        previousData = previousDriver.points;
        currentData = currentDriver.points;
      }
    
      const answerIsCorrect =
        (guess === 'higher' && currentData <= previousData) ||
        (guess === 'lower' && currentData >= previousData);
    
    
      if (answerIsCorrect) {
        score++;
        currentDriverIndex = previousDriverIndex;
        previousDriverIndex = null;
        showNextDriver();
      } else {
        endGame();
      }
    }
    
    
    function endGame() {
      // Remove event listeners from the buttons
      higherButton.removeEventListener('click', onHigherButtonClicked);
      lowerButton.removeEventListener('click', onLowerButtonClicked);
    
      let message = "";
      if (score <= 1) {
        const messages = [
          "You may need to get a new pit crew - they're clearly not feeding you the right information!",
          "That answer is a bit like a car stuck in the gravel trap - not quite what we were hoping for!",
          "Looks like you need to spend less time watching the races and more time studying the history books!",
          "Looks like you need some more practice laps before you get the hang of this."
        ];
        const randomIndex = Math.floor(Math.random() * messages.length);
        message = `${messages[randomIndex]} ${message}`;
      } else if (score <= 4) {
        const messages = [
          "Let's just say, if you were driving in the F1, you'd be lapped by now.",
          "Very Bad - You might want to stick to bumper cars!",
          "Don't worry, even the best drivers have their off days. Maybe you'll do better next time.",
          "Well, that answer was definitely not pole position material."
        ];
        const randomIndex = Math.floor(Math.random() * messages.length);
        message = `${messages[randomIndex]} ${message}`;
      } else if (score <= 10) {
        const messages = [
          "You're like a midfield driver - solid, but not quite podium material.",
          "You're doing okay, but maybe you should watch a few more races before playing again.",
          "You're not exactly setting the track on fire, but you're not stalling out either.",
          "Not bad, not bad at all! You're definitely on the right track to becoming an F1 expert."
        ];
        const randomIndex = Math.floor(Math.random() * messages.length);
        message = `${messages[randomIndex]} ${message}`;
      } else {
        const messages = [
          "I think we need to do a doping test on you because that score is unreal!",
          "Congratulations! You just set a new lap record for F1 trivia. Absolutely amazing!",
          "Wow, you're like the Lewis Hamilton of F1 trivia! Impressive!",
          "Hold on, let me check if you're not secretly connected to the FIA. Your knowledge is on another level!"
        ];
        const randomIndex = Math.floor(Math.random() * messages.length);
        message = `${messages[randomIndex]} ${message}`;
      }
    
      // Display the user's score and message
      resultContainer.textContent = `Game over! You got ${score} correct. ${message}`;
      playAgainButton.style.display = 'block';
      playAgainButton.addEventListener('click', startGame);
    }

console returns output for querySelectorAll as null even when Node exists

I am trying to use javascript to find element containing a class among bunch of elements and assign its index no to a variable, but the output of following code is always null, even when the document contains element with the class. Alert windows shows 25.

elementzParent = document.querySelectorAll(".question-counter i");
alert(elementzParent.length);
console.log(elementzParent);
for (let i = 0; i < elementzParent.length; i++) {
  elementzclass = elementzParent[i].classList;
  console.log(elementzclass);
  if (elementzclass.contains('fa-lg')) {

    var PYQNo = i + 1;
    console.log(PYQNo);
  };
};

If I change the console.log to console.info

elementzParent = document.querySelectorAll(".question-counter i");
alert(elementzParent.length);
console.info(elementzParent);
for (let i = 0; i < elementzParent.length; i++) {
  elementzclass = elementzParent[i].classList;
  console.info(elementzclass);
  if (elementzclass.contains('fa-lg')) {

    var PYQNo = i + 1;
    console.log(PYQNo);
  };
};

the output becomes 25 in alert window and

NodeList(25) [ i.fa.fa-circle.ng-tns-c105-1.fa-lg.correct, i.fa.fa-circle.ng-tns-c105-1, i.fa.fa-circle.ng-tns-c105-1, i.fa.fa-circle.ng-tns-c105-1, i.fa.fa-circle.ng-tns-c105-1, i.fa.fa-circle.ng-tns-c105-1, i.fa.fa-circle.ng-tns-c105-1, i.fa.fa-circle.ng-tns-c105-1, i.fa.fa-circle.ng-tns-c105-1, i.fa.fa-circle.ng-tns-c105-1, … ]
DOMTokenList(5) [ "fa", "fa-circle", "ng-tns-c105-1", "fa-lg", "correct" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
DOMTokenList(3) [ "fa", "fa-circle", "ng-tns-c105-1" ]
undefined

HTML is

   <div _ngcontent-oly-c105="" class="question-counter ng-tns-c105-1">   
      <span _ngcontent-oly-c105="" class="ng-tns-c105-1 ng-star-inserted" style="">
        <span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1 fa-lg correct"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><span _ngcontent-oly-c105="" class="question-progress-bar ng-tns-c105-1 ng-star-inserted">
          <i _ngcontent-oly-c105="" aria-hidden="true" class="fa fa-circle ng-tns-c105-1"></i>
        </span><!---->
      </span><!---->
      <!---->
    </div>

I trying javascript for first time by reading from web and running this in firefox console. I would like some guidance as to why my code may not be working?

I tried to use getAttribute() instead of classlist first but that didn’t work too.
Tried console.info which returns all the matching nodes, but it was of no benefit.
Also tried getElementsByClassName instead of querySelectorAll still null output.
Also tried using window.onload.
Works on codepen.io

Transform array to the following format

I have an array of objects that have 2 fields key and type, the type field is practice or theory

Result:

  1. group the array by key

  2. transform the array: in the new array the object with type practice should come in the even index and object with type theory should be in the odd index. (check the input and the output if my explanation wasn’t clear)

here’s my code but it doesn’t work as expected in the transform the array

function transformArray(arr) {
  const grouped = arr.reduce((result, item) => {
    const key = item.key;
    if (!result[key]) {
      result[key] = { key, values: [] };
    }
    result[key].values.push(item);
    return result;
  }, {});

  for (const group in grouped) {
    const values = grouped[group].values;
    const newValues = [];
    for (let i = 0; i < values.length; i++) {
      const item = values[i];
      if (item.type === 'practice' && i % 2 === 0) {
        newValues.push(item);
      } else if (item.type === 'theory' && i % 2 === 1) {
        newValues.push(item);
      }
    }
    grouped[group].values = newValues;
  }

  return Object.values(grouped);
}

example input:

const input = [
{ key: 'A', type: 'practice' },
{ key: 'A', type: 'practice' },
{ key: 'A', type: 'theory' },
{ key: 'A', type: 'theory' },

{ key: 'B', type: 'practice' },
{ key: 'B', type: 'theory' },
{ key: 'B', type: 'practice' },

{ key: 'C', type: 'practice' },
{ key: 'C', type: 'theory' },
{ key: 'C', type: 'practice' },
]

output

[
  {
    key: 'A',
    values: [
      { key: 'A', type: 'practice'},  // index = even ==> practice
      { key: 'A', type: 'theory' },    // index = odd ==> theory
      { key: 'A', type: 'practice'}, // index = even ==> practice
      { key: 'A', type: 'theory'}, // index = odd ==> theory
    ],
  },
  {
    key: 'B',
    values: [
      { key: 'B', type: 'practice' },
      { key: 'B', type: 'theory',},
      { key: 'B', type: 'practice' },
    ],
  },
  {
    key: 'C',
    values: [
      { key: 'C', type: 'practice' },
      { key: 'C', type: 'theory', },
      { key: 'C', type: 'practice'},
    ],
  },
]

how can i convert the html file to a jsx file?

function calculate() {
  var num1, num2, num3, res;

  num1 = Number(document.getElementById('length').value);
  num2 = Number(document.getElementById('width').value);
  num3 = Number(document.getElementById('height').value);
  res = num1 * num2 * num3;
  document.formcalcvolume.volume.value = (res).toFixed(2);

  document.getElementById("tbl").innerHTML = "";

  if (res > 0) {

    var table = `<tr>
                              <td data-col-title="Name" class="tabledatastyle"><b>${"GEN S"}</b></td>
                              <td data-col-title="CADR (m3/h)">${180}</td>
                              <td data-col-title="Volume">${res.toFixed(2)}</td>
                              <td data-col-title="100% ACH">${(180/res).toFixed(2)}</td>
                              <td data-col-title="50% ACH">${(90/res).toFixed(2)}</td>
                          </tr>`;
    document.getElementById('tbl').innerHTML += table;

    var table = `<tr>
                              <td data-col-title="Name" class="tabledatastyle"><b>${"GEN X"}</b></td>
                              <td data-col-title="CADR (m3/h)">${727}</td>
                              <td data-col-title="Volume">${res.toFixed(2)}</td>
                              <td data-col-title="100% ACH">${(727/res).toFixed(2)}</td>
                              <td data-col-title="50% ACH">${(727/(res*2)).toFixed(2)}</td>
                          </tr>`;
    document.getElementById('tbl').innerHTML += table;

    var table = `<tr>
                              <td data-col-title="Name" class="tabledatastyle"><b>${"GEN Y"}</b></td>
                              <td data-col-title="CADR (m3/h)">${633}</td>
                              <td data-col-title="Volume">${res.toFixed(2)}</td>
                              <td data-col-title="100% ACH">${(633/res).toFixed(2)}</td>
                              <td data-col-title="50% ACH">${(633/(res*2)).toFixed(2)}</td>
                          </tr>`;
    document.getElementById('tbl').innerHTML += table;

    var table = `<tr>
                              <td data-col-title="Name" class="tabledatastyle"><b>${"GEN Z"}</b></td>
                              <td data-col-title="CADR (m3/h)">${1156}</td>
                              <td data-col-title="Volume">${res.toFixed(2)}</td>
                              <td data-col-title="100% ACH">${(1156/res).toFixed(2)}</td>
                              <td data-col-title="50% ACH">${(1156/(res*2)).toFixed(2)}</td>
                          </tr>`;
    document.getElementById('tbl').innerHTML += table;

    clearForm();

  } else reset();
}

function clearForm() {
  document.getElementById('length').value = null;
  document.getElementById('height').value = null;
  document.getElementById('width').value = null;

}

function reset() {
  document.getElementById('length').value = null;
  document.getElementById('height').value = null;
  document.getElementById('width').value = null;
  document.getElementById('volume').value = null;

  document.getElementById("tbl").innerHTML = "";
}

function cleartable() {}
<div class="boddy">

  <div class="total">
    <div class="cadr-info">
      <form name="formcalcvolume" id="form1" class="classicForm">
        <h3 style="color:rgb(64,141,194)">Room Volume</h3>
        <p>
          <label><b>Length (m)</b><b style="color: red">*</b></label>
          <input type="text" id="length" />
        </p>
        <p>
          <label><b>Width (m)</b><b style="color: red">*</b></label>
          <input type="text" id="width" />
        </p>
        <p>
          <label><b>Height (m)</b><b style="color: red">*</b></label>
          <input type="text" id="height" />
        </p>
        <p>
          <button type="button" onclick="calculate()">Calculate</button>
        </p>
        <p>
          <button type="button" onclick="reset()">Reset</button>
        </p>
        <p>
          <label>Room Volume  (m3)</label>
          <input type="text" id="volume" />
        </p>
      </form>
    </div>
    <div class="cadr-info">
      <h3 style="color:rgb(64,141,194)"><b>Air Changes per Hour</b></h3>

      <form class="cadr-form">
        <table id="cadrtable" class="cadr-table" style="width:100%">
          <thead class="tableheading">
            <tr>
              <th scope="col" style="background-color:#6a78ed; color:white;"><b>Name</b></th>
              <th scope="col" style="background-color:#6a78ed; color:white;"><b>CADR(m3/h)</b></th>

              <th scope="col" style="background-color:#6a78ed; color:white;"><b>Room Volume</b></th>
              <th scope="col" style="background-color:#6a78ed; color:white;"><b>100% ACH</b></th>
              <th scope="col" style="background-color:#6a78ed; color:white;"><b>50% ACH</b></th>
            </tr>

          </thead>
          <tbody id="tbl" class="tablecontent"></tbody>
        </table>

      </form>
      <h4 id="emaillink" style="color:rgb(64,141,194)">For a more detailed report, contact us on <br>[email protected]</h4>
    </div>

  </div>
</div>

How would I force react to reconstruct component? [duplicate]

This might be a stupid question but I have some useEffects that act as initial triggers and set up the component.
Now, I could trigger all these useEffects with some flag in the dependancy array and kinda fake a “reconstruction” of the component but is there a way to do it properly?

So that the component rerenders as if its doing it for the first time?
Thanks for any suggestions…

I want a solution to content_security_policy refuse to load facebook sdk codes in chrome extension manifest v3

I am building a chrome extension
And I add the following code to a page within its files

window.fbAsyncInit = function () {
FB.init({
appId: "761023588971600",
autoLogAppEvents: true,
xfbml: true,
version: "v16.0",
});
};
var script = document.createElement("script");
script.async = true;
script.defer = true;
script.crossOrigin = "anonymous";
script.src = "https://connect.facebook.net/en_US/sdk.js";
document.head.appendChild(script);

my manifest.json

{
"manifest_version": 3,
"name": "Ultra Share Bot",
"description": "Share with ease",
"version": "1.0",
"icons": {
"16": "img/share_icon.png",
"32": "img/share_icon.png",
"48": "img/share_icon.png",
"128": "img/share_icon.png"
},
"action": {
"default_popup": "popup.html",
"default_icon": "img/share_icon.png",
"default_title": "Share with ease now"
},
"background": {
"service_worker": "background.js"
},
"permissions": [
"tabs"
]
}

These two errors show me how to solve it

Refused to load the script 'https://connect.facebook.net/en_US/sdk.js' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
Refused to load the script 'https://connect.facebook.net/en_US/sdk.js' because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:*". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

I tried adding this code to a file manifest.json

"content_security_policy": {
    "extension_pages": "script-src 'self' https://connect.facebook.net; object-src 'self';"
  }

But it didn’t work out
Once the hosting was updated, Chrome blocked it and showed the following error

Error
'content_security_policy.extension_pages': Insecure CSP value "https://connect.facebook.net" in directive 'script-src'.
Could not load manifest.

Cannot read properties of undefined (reading ‘push’) in node js

i’m trying to add roomSchema to a userSchema

this is my code

router.post('/join-room', async (req, res) => {
  const { roomId, userId } = req.body;
  try {
    const user = await User.findById(userId);
    const room = await Room.findById(roomId);
    if (!user || !room) {
      return res.status(404).json({ message: 'User or room not found' });
    }
    user.rooms.push(roomId);
    await user.save();
    res.json({ message: 'User joined room successfully' });
  } catch (error) {
    console.error(error);
  }
});

this is my json


{
  _id: new ObjectId("6436c40c989d571ad31563a8"),
  name: 'jquery',
  email: '[email protected]',
  password: '$2a$10$fdPk3EzPPZc4SDxGmYnj3usFm9IlU0SNb.Ek4hINXHTfNSAclscxW',
  __v: 0
} {
  _id: new ObjectId("6436bf25f70ece2db5576081"),
  created_date: 2023-04-12T14:24:37.439Z,
  name: 'vue',
  __v: 0
}

this my error

 Cannot read properties of undefined (reading 'push')

please how can i go about this

How to add useEffect hook in nextjs with antd

This is my first project in next.js, I am trying to add an existing ProLayout component from the ant design library
I understand that the error I am getting is because my app is being rendered on the server side, right at that moment the dom does not exist, for that reason you don’t get the document because it does not exist.

I understand that.
What I don’t understand is how to implement the useEffect hook inside the component because document is inside the return

Error:

Server Error
ReferenceError: document is not defined

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Source
src/pages/index.tsx (349:14) @ document

  347 | return [
  348 |   props.layout !== "side" &&
> 349 |   document.body.clientWidth > 1400 ? (
      |  ^
  350 |     <SearchInput />
  351 |   ) : undefined,
  352 |   <InfoCircleFilled key="InfoCircleFilled" />,

What I need:

I need to implement useEffect inside Index

Index

import {
  CaretDownFilled,
  DoubleRightOutlined,
  GithubFilled,
  InfoCircleFilled,
  LogoutOutlined,
  PlusCircleFilled,
  QuestionCircleFilled,
  SearchOutlined,
} from "@ant-design/icons";
import type { ProSettings } from "@ant-design/pro-components";
import {
  PageContainer,
  ProCard,
  ProConfigProvider,
  ProLayout,
  SettingDrawer,
} from "@ant-design/pro-components";
import { css } from "@emotion/css";
import {
  Button,
  Divider,
  Input,
  Dropdown,
  Popover,
  theme,
} from "antd";
import React, { useEffect, useState } from "react";
import defaultProps from "./_defaultProps";

const Item: React.FC<{ children: React.ReactNode }> = (props) => {
  const { token } = theme.useToken();
  return (
    <div
      className={css`
        color: ${token.colorTextSecondary};
        font-size: 14px;
        cursor: pointer;
        line-height: 22px;
        margin-bottom: 8px;
        &:hover {
          color: ${token.colorPrimary};
        }
      `}
      style={{
        width: "33.33%",
      }}
    >
      {props.children}
      <DoubleRightOutlined
        style={{
          marginInlineStart: 4,
        }}
      />
    </div>
  );
};

const List: React.FC<{
  title: string;
  style?: React.CSSProperties;
}> = (props) => {
  const { token } = theme.useToken();

  return (
    <div
      style={{
        width: "100%",
        ...props.style,
      }}
    >
      <div
        style={{
          fontSize: 16,
          color: token.colorTextHeading,
          lineHeight: "24px",
          fontWeight: 500,
          marginBlockEnd: 16,
        }}
      >
        {props.title}
      </div>
      <div
        style={{
          display: "flex",
          flexWrap: "wrap",
        }}
      >
        {new Array(6).fill(1).map((_, index) => {
          return <Item key={index}>具体的解决方案-{index}</Item>;
        })}
      </div>
    </div>
  );
};

const MenuCard = () => {
  const { token } = theme.useToken();
  return (
    <div
      style={{
        display: "flex",
        alignItems: "center",
      }}
    >
      <Divider
        style={{
          height: "1.5em",
        }}
        type="vertical"
      />
      <Popover
        placement="bottom"
        overlayStyle={{
          width: "calc(100vw - 24px)",
          padding: "24px",
          paddingTop: 8,
          height: "307px",
          borderRadius: "0 0 6px 6px",
        }}
        content={
          <div style={{ display: "flex", padding: "32px 40px" }}>
            <div style={{ flex: 1 }}>
              <List title="金融解决方案" />
              <List
                title="其他解决方案"
                style={{
                  marginBlockStart: 32,
                }}
              />
            </div>

            <div
              style={{
                width: "308px",
                borderInlineStart: "1px solid " + token.colorBorder,
                paddingInlineStart: 16,
              }}
            >
              <div
                className={css`
                  font-size: 14px;
                  color: ${token.colorText};
                  line-height: 22px;
                `}
              >
                热门产品
              </div>
              {new Array(3).fill(1).map((name, index) => {
                return (
                  <div
                    key={index}
                    className={css`
                      border-radius: 4px;
                      padding: 16px;
                      margin-top: 4px;
                      display: flex;
                      cursor: pointer;
                      &:hover {
                        background-color: ${token.colorBgTextHover};
                      }
                    `}
                  >
                    <img src="https://gw.alipayobjects.com/zos/antfincdn/6FTGmLLmN/bianzu%25252013.svg" />
                    <div
                      style={{
                        marginInlineStart: 14,
                      }}
                    >
                      <div
                        className={css`
                          font-size: 14px;
                          color: ${token.colorText};
                          line-height: 22px;
                        `}
                      >
                        Ant Design
                      </div>
                      <div
                        className={css`
                          font-size: 12px;
                          color: ${token.colorTextSecondary};
                          line-height: 20px;
                        `}
                      >
                        杭州市较知名的 UI 设计语言
                      </div>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        }
      >
        <div
          style={{
            color: token.colorTextHeading,
            fontWeight: 500,
            cursor: "pointer",
            display: "flex",
            gap: 4,
            paddingInlineStart: 8,
            paddingInlineEnd: 12,
            alignItems: "center",
          }}
          className={css`
            &:hover {
              background-color: ${token.colorBgTextHover};
            }
          `}
        >
          <span> 企业级资产中心</span>
          <CaretDownFilled />
        </div>
      </Popover>
    </div>
  );
};

const SearchInput = () => {
  const { token } = theme.useToken();
  return (
    <div
      key="SearchOutlined"
      aria-hidden
      style={{
        display: "flex",
        alignItems: "center",
        marginInlineEnd: 24,
      }}
      onMouseDown={(e) => {
        e.stopPropagation();
        e.preventDefault();
      }}
    >
      <Input
        style={{
          borderRadius: 4,
          marginInlineEnd: 12,
          backgroundColor: token.colorBgTextHover,
        }}
        prefix={
          <SearchOutlined
            style={{
              color: token.colorTextLightSolid,
            }}
          />
        }
        placeholder="搜索方案"
        bordered={false}
      />
      <PlusCircleFilled
        style={{
          color: token.colorPrimary,
          fontSize: 24,
        }}
      />
    </div>
  );
};


const Index = ():JSX.Element => {
  const [settings, setSetting] = useState<
    Partial<ProSettings> | undefined
  >({
    fixSiderbar: true,
    layout: "mix",
    splitMenus: true,
  });

  const [pathname, setPathname] = useState(
    "/list/sub-page/sub-sub-page1"
  );
  const [num, setNum] = useState(40);

    // 
    // useEffect
    useEffect(() => {
      // page loaded
      document.title = `page loaded!`;
    });
  
  return (
    <div
      id="test-pro-layout"
      style={{
        height: "100vh",
      }}
    >
      <ProConfigProvider hashed={false}>
        <ProLayout
          prefixCls="my-prefix"
          bgLayoutImgList={[
            {
              src: "https://img.alicdn.com/imgextra/i2/O1CN01O4etvp1DvpFLKfuWq_!!6000000000279-2-tps-609-606.png",
              left: 85,
              bottom: 100,
              height: "303px",
            },
            {
              src: "https://img.alicdn.com/imgextra/i2/O1CN01O4etvp1DvpFLKfuWq_!!6000000000279-2-tps-609-606.png",
              bottom: -68,
              right: -45,
              height: "303px",
            },
            {
              src: "https://img.alicdn.com/imgextra/i3/O1CN018NxReL1shX85Yz6Cx_!!6000000005798-2-tps-884-496.png",
              bottom: 0,
              left: 0,
              width: "331px",
            },
          ]}
          {...defaultProps}
          location={{
            pathname,
          }}
          siderMenuType="group"
          menu={{
            collapsedShowGroupTitle: true,
          }}
          avatarProps={{
            src: "https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg",
            size: "small",
            title: "七妮妮",
            render: (props, dom) => {
              return (
                <Dropdown
                  menu={{
                    items: [
                      {
                        key: "logout",
                        icon: <LogoutOutlined />,
                        label: "退出登录",
                      },
                    ],
                  }}
                >
                  {dom}
                </Dropdown>
              );
            },
          }}
          actionsRender={(props) => {
            if (props.isMobile) return [];
            return [
              props.layout !== "side" &&
              document.body.clientWidth > 1400 ? (
                <SearchInput />
              ) : undefined,
              <InfoCircleFilled key="InfoCircleFilled" />,
              <QuestionCircleFilled key="QuestionCircleFilled" />,
              <GithubFilled key="GithubFilled" />,
            ];
          }}
          headerTitleRender={(logo, title, _) => {
            const defaultDom = (
              <a>
                {logo}
                {title}
              </a>
            );
            if (document.body.clientWidth < 1400) {
              return defaultDom;
            }
            if (_.isMobile) return defaultDom;
            return (
              <>
                {defaultDom}
                <MenuCard />
              </>
            );
          }}
          menuFooterRender={(props) => {
            if (props?.collapsed) return undefined;
            return (
              <div
                style={{
                  textAlign: "center",
                  paddingBlockStart: 12,
                }}
              >
                <div>© 2021 Made with love</div>
                <div>by Ant Design</div>
              </div>
            );
          }}
          onMenuHeaderClick={(e) => console.log(e)}
          menuItemRender={(item, dom) => (
            <div
              onClick={() => {
                setPathname(item.path || "/welcome");
              }}
            >
              {dom}
            </div>
          )}
          {...settings}
        >
          <PageContainer
            token={{
              paddingInlinePageContainerContent: num,
            }}
            extra={[
              <Button key="3">操作</Button>,
              <Button key="2">操作</Button>,
              <Button
                key="1"
                type="primary"
                onClick={() => {
                  setNum(num > 0 ? 0 : 40);
                }}
              >
                主操作
              </Button>,
            ]}
            subTitle="简单的描述"
            footer={[
              <Button key="3">重置</Button>,
              <Button key="2" type="primary">
                提交
              </Button>,
            ]}
          >
            <ProCard
              style={{
                height: "200vh",
                minHeight: 800,
              }}
            >
              <div />
            </ProCard>
          </PageContainer>

          <SettingDrawer
            pathname={pathname}
            enableDarkTheme
            getContainer={() =>
              document.getElementById("test-pro-layout")
            }
            settings={settings}
            onSettingChange={(changeSetting) => {
              setSetting(changeSetting);
            }}
            disableUrlParams={false}
          />
        </ProLayout>
      </ProConfigProvider>
    </div>
  );
};

export default Index;

Links:

https://codesandbox.io/s/eoy3s9

https://procomponents.ant.design/en-US/components/layout?tab=api