React传播操作符(..props)不按预期工作?



我试图通过一个GeolocationCoordinates对象到使用传播操作符(https://reactjs.org/docs/jsx-in-depth.html#spread-attributes)的子组件,但由于某种原因在子道具它只是一个空对象:

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>
)
}

console (Map子道具为空):

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

然而,如果在定义子地图标签时在父组件中手动指定props,一切都可以工作(实际上我得到警告地图缺少属性,因为我只想要纬度和经度):

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

console (Map子道具已经定义):

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
}
]
]
}

package.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对象。这就是为什么我在配置中添加了松散选项,它仍然没有帮助。我是否从根本上误解了如何使用这个算子?我的设置有问题吗?

我已经在这个问题上搜索了一堆,大多数人似乎试图在React之外的对象上使用操作符,或者在编译操作符时出现问题,这不是我的问题。我知道这是可选的,我可以在没有这个功能的情况下构建我的应用程序的其余部分,但我预见我的组件会变得更加复杂,能够只传递整个props对象而不手动指定每个字段将是一个很大的帮助。非常感谢所有能帮助我的人。

在布尔上下文中遇到空对象时被认为是true。请看这里:真相。

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>

最新更新