如何使用字符串来查找对象键?



如何在主题对象中使用react组件prop中使用的字符串选择对象键?

主题
{
palette: {
primary: {
main: '#dc2626',
dark: '#7f1d1d',
light: '#fecaca',
}
text: '#111827',
}
}

组件

const Typography = ({ color, children }) => (
<p style={{ color: theme.palette[color] }}>{children}</p>
);

我想如何使用组件:

<Typography color='primary.main'>Hello world</Typography>

让我知道这是一个不好的做法,无论如何都应该避免。

我试图使用eval函数,但发现它不安全,被认为是一个不好的做法。

如果您只是想了解如何在对象中获取嵌套字段,您应该查看lodash的get函数。

例子:

export default const theme = {
palette: {
primary: {
main: '#dc2626',
dark: '#7f1d1d',
light: '#fecaca',
}
text: '#111827',
}
};

组件

import { get } from lodash library;
import theme from './theme.js';
export default function MyComponent({ children }) {
const nestedFieldPath = 'palette.primary.main';
// Get nested field value
const nestedFieldValue = get(theme, nestedFieldPath);
return <p color={nestedFieldValue}>{children}</p>
}

你可以创建一个钩子,它可以扩展,也可以处理默认情况下没有颜色被传递给你的排版组件

例钩:

import React from "react";
const useColor = (color = null) => {
// Set the default theme
const [selectedTheme, setSelectedTheme] = React.useState(["primary", "main"]);
React.useEffect(() => {
if (color) {
setSelectedTheme(color.split("."));
}
}, [color]);
return selectedTheme;
};
export default useColor;

然后是Typography组件,你从钩子返回一个数组,所以把它解构成2个值。命名当然是有问题的:

const Typography = ({ color, children }) => {
const [level, choice] = useColor(color);
return <p style={{ color: theme.palette[level][choice] }}>{children}</p>;
};

用法:

<Typography color={"primary.main"}>Hello</Typography>

codesandbox: https://codesandbox.io/s/clever-julien-rr0tuf?file=/src/App.js:506-561

这将是我的解决方案,不使用任何额外的库.

的想法是创建一个函数的方法来获取嵌套的颜色值从你的主题对象,然后使用该函数(getColor)在你的组件。

这可以处理额外的嵌套级别。

请记住,我使用React的经验是阅读3页的文档。从问题中还不清楚,当你试图获得不在主题中的颜色时,你要如何处理这种情况,你必须在减少中处理。

function Theme () {
let palette = {
primary: {
main: '#dc2626',
dark: '#7f1d1d',
light: '#fecaca',
},
secondary : {
green: {
lightgreen : 'myfancycolor :)'
} 
}
}
this.getColor = function(string){
let nesting = string.split(".");
const result = nesting.reduce(
(accumulator, currentValue) => {
if (accumulator[currentValue])
return accumulator[currentValue];
else
return accumulator
} ,
palette
);
return result;
}
}
let myTheme = new Theme();
console.log(myTheme.getColor("secondary.green.lightgreen"))
//prints myfancycolor :)

在组件中的用法:

const Typography = ({ color, children }) => (
<p style={{ color: myTheme.getColor("primary.dark") }}>{children}</p>
);

最新更新