如何在主题对象中使用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>
);