簡體   English   中英

React 傳播運算符 (...props) 沒有按預期工作?

[英]React spread operator (...props) not working as expected?

我正在嘗試使用傳播運算符( https://reactjs.org/docs/jsx-in-depth.html#spread-attributes )將 GeolocationCoordinates 對象傳遞給子組件,但由於某種原因在子道具中它只是空對象:

interface HUDState {
    geoCoords: GeolocationCoordinates | null
    login: boolean
}

function MainHUD(props: HUDState) {
    console.log('MainHUD props:', props)
   
    return (
        <Background>
            {
             props.geoCoords !== null && props.geoCoords !== undefined ? 
                 <Map {...props.geoCoords} /> 
            : 
              null
            }
        </Background>
    )
}

function Map(props: GeolocationCoordinates) {
    console.log('Map props:', props)

        return (
            <MapContainer style={MapContainerStyle} center={[props.latitude, props.longitude]} zoom={13} scrollWheelZoom={false}>
                <TileLayer
                    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />
            </MapContainer>
        )
}

控制台(地圖子道具為空):

MainHUD props: Object { login: false, geoCoords: GeolocationCoordinates }
Map props: Object {  } <-- Why is this empty here?

但是,如果在定義子地圖標記時在父組件中手動指定道具,一切正常(實際上我收到警告 Map is missing properties 因為我只想要緯度和經度):

<Map latitude={props.geoCoords.latitude} longitude={props.geoCoords.longitude} />

控制台(現在定義了地圖子道具):

Map props: Object { latitude: 40.2927067, longitude: -73.9837427 } <-- Not empty now!

我正在使用 webpack/babel 將我的 tsx 轉譯回 javascript,它沒有拋出任何錯誤。 我已經包含了"@babel/plugin-transform-spread" ,盡管這篇文章( https://babeljs.io/docs/en/babel-plugin-transform-spread )說它應該包含在"@babel/env"預設。 我也將插件添加到 webpack.config.js 和 .babelrc 中,因為我不確定哪個需要它。

webpack.config.js:

const path = require('path');

module.exports = {
    entry: path.resolve(__dirname, './src/App.tsx'),
    module: {
        rules: [
            {
                test: /\.(ts|js)x?$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: [
                                "@babel/env",
                                "@babel/react",
                                "@babel/typescript"
                            ],
                            plugins: [
                                ["@babel/plugin-transform-spread", {
                                    "loose": true
                                }]
                            ]
                        },
                    }
                ]
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader'],
            },
        ]
    },
    resolve: {
        extensions: ['*', '.json', '.js', '.jsx', '.ts', '.tsx']
    },
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'app.bundle.js',
    },
    devServer: {
        static: {
            directory: path.join(__dirname, './dist'),
        },
        server: {
            type: 'https',
            options: {
                key: './example.com+4-key.pem',
                cert: './example.com+4.pem',
            }
        }
    }
}

.babelrc:

{
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react",
        "@babel/preset-typescript"
    ],
    "plugins": [
        [
            "@babel/plugin-transform-spread",
            {
                "loose": true
            }
        ]
    ]
}

包.json:

{
  "name": "example.com",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@types/react": "^18.0.26",
    "@types/react-dom": "^18.0.9",
    "@types/styled-components": "^5.1.26",
    "leaflet": "^1.9.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-hook-form": "^7.40.0",
    "react-leaflet": "^4.2.0",
    "styled-components": "^5.3.6"
  },
  "devDependencies": {
    "@babel/core": "^7.20.5",
    "@babel/plugin-proposal-object-rest-spread": "^7.20.2",
    "@babel/plugin-transform-spread": "^7.19.0",
    "@babel/preset-env": "^7.20.2",
    "@babel/preset-react": "^7.18.6",
    "@babel/preset-typescript": "^7.18.6",
    "babel-loader": "^9.1.0",
    "css-loader": "^6.7.2",
    "style-loader": "^3.3.1",
    "typescript": "^4.9.4",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.11.1"
  }
}

我已經吃飽了,我補充說

props.geoCoords !== null && props.geoCoords !== undefined

在渲染子 Map 組件之前,它仍然什么都不做。 我也理解傳播運算符意味着像數組這樣的可迭代對象,但是在 React 和我上面鏈接的 React 示例中,它用於 props 對象。 這就是為什么我在配置中添加了 loose 選項,但它仍然無濟於事。 我是否從根本上誤解了有關如何使用此運算符的某些內容? 我的設置有問題嗎?

我在這個問題上搜索了很多,大多數人似乎試圖在 React 之外的對象上使用運算符,或者首先在轉換運算符時遇到問題,這不是我的問題。 我知道這是可選的,我可以在沒有這個功能的情況下構建我的應用程序的其余部分,但我預見到我的組件會變得更加復雜並且能夠只傳遞整個道具對象而無需手動指定每個字段將是一個很大的幫助。 非常感謝任何可以幫助我的人。

布爾上下文中遇到空對象時被認為是true 看看這里: Truthy

const geoCoords = {};

console.log(geoCoords !== null && geoCoords !== undefined); // true

因此,如果geoCoords是一個空對象 ( {} ), <Map {...props.geoCoords} />仍將被渲染,但不會傳遞任何道具。

確保geoCoords不是空對象,您可以執行以下操作:

<Background>
  {props.geoCoords && <Map {...props.geoCoords} />}
</Background>

或者也檢查是否是一個空對象:

<Background>
    {props.geoCoords && Object.keys(props.geoCoords).length > 0 && (
      <Map {...props.geoCoords} />
    )}
</Background>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM