我将如何基于其父组件的道具将条件样式应用于样式组件?
下面是我当前代码的高级示例设置:
// File 1: GrandParent.js
import React, { useState } from 'react';
import Parent from './parent';
export default function GrandParent() {
const [ isExpanded, setIsExpanded ] = useState(false);
render (
<>
<Parent isExpanded={isExpanded} />
...other Stuff
</>
);
}
// File 2: Parent.js
import React from 'react';
import styled from 'styled-components';
import mediaQueries from './settings';
export default function Parent(props) {
render (
<div className={props.isExpanded ? `expanded` : ``}>
... other stuff
<Child>I'm a child.</Child>
</>
);
}
const Child = styled.div`
background-color: "red";
.expanded & {
background-color: "blue";
${mediaQueries.desktop`
background-color: "navy";
`}
}
`;
本质上,我想要的是让<Child>
样式的组件知道<Parent>
的道具,以便可以有条件地对其进行样式设置。目前,我只是有条件地将类名应用于<Parent>
内的div,然后使用该类名将样式应用于<Child>
。但是感觉不像是一种非常样式化的组件或React的处理方式。
我想做的是更多这样的事情:
const Child = styled.div`
background-color: ${props => props.isExpanded ? 'blue' : 'red'};
`;
但是我是否有办法不必在<Child>
上传递'isExpanded'作为道具呢?在我的实际代码中,还有更多<Parent>
的子代也需要知道'isExpanded'的状态以用于样式设计,我真的不想将那个道具单独传递给他们
我认为Context API可能是这里的关键,但是我已经在React树中的GrandParent
上方几级使用了上下文来进行全局样式设置,而且我担心如果尝试嵌套第二个上下文(可能将其包装在<Parent>
周围,以使<Parent>
及其所有子代知道'isExpanded'的状态),然后<Parent>
和<Child>
可能无法访问外部上下文...或者不是上下文嵌套如何工作?
我只知道我仍然需要<Parent>
和<Child>
才能从外部上下文访问某些主题设置。而且我不知道在<Parent>
级别引入第二上下文仅仅是跟踪该单个“ isExpanded”道具的状态是否过大。
这里的另一个要求是,我还需要<Child>
才能处理其条件样式内的媒体查询(例如,如果'isExpanded'为true且为桌面视口,则仅应用某些样式)。
什么是正确的设置方式?
答案 0 :(得分:1)
您是正确的。上下文是必经之路。
上下文被设计为轻量级的跨组件数据存储,在这种情况下使用2个上下文绝对不是矫kill过正。实际上,此用例几乎就是为Context创建的。 (有趣的是,在工作中,我们使用了数十个嵌套上下文)。
export const ExpandedContext = createContext();
export default function GrandParent() {
const [ isExpanded, setIsExpanded ] = useState(false);
render (
<ExpandedContext.Provider value={{ isExpanded }}>
<Parent />
...other Stuff
<ExpandedContext.Provider/>
);
}
不幸的是,无法访问样式化组件内部的上下文,因此您必须通过props传递值。
export default function Parent(props) {
const { isExpanded } = useContext(ExpandedContext);
render (
<div>
... other stuff
<Child isExpanded={isExpanded}>I'm a child.</Child>
</div>
);
}
答案 1 :(得分:1)
您可以将父级容器div
设置为样式组件,并将refer设置为Child
。像这样:
export default function Parent(props) {
render (
<ParentContainer isExpanded={props.isExpanded}>
... other stuff
<Child>I'm a child.</Child>
</ParentContainer>
);
}
const Child = styled.div`
// ...
`;
const ParentContainer = styled.div`
> ${Child} {
background-color: ${props => props.isExpanded ? 'blue' : 'red'};
}
`;