有没有办法隐式地将 props 传递给组件?
Is there a way to pass down props to a component implicitly?
我希望能够为我的所有组件设置一个全局主题(变量集)以继承和扩展它们的默认变量。例如,我有一个 button
组件,它具有默认样式(内联 CSS),它引用一组变量,例如 primaryColor
,...我希望能够在我使用这些组件的任何地方轻松更新这些变量,而无需将它们显式传递给组件。
例如,我想要以下行为,我可以 (1) 将它们包装在一个组件中并让 primaryColor
级联到每个 Button
组件,或者 (2) 导出它高阶组件中的组件和提要更新道具等......但是,我无法使用这些方法中的任何一种。或许,有更好的方法或者...
(1)
render() {
return (
<Theme variables={{ 'primaryColor': 'red' }}>
<Button />
<SecondButton />
<ThirdButton />
</Theme>
);
}
(2)
render() {
return (
<div>
<Button />
<SecondButton />
<ThirdButton />
</div>
);
}
export default Theme(SampleComponent)
此方法有效,因为它显然已明确传递给每个组件:
render() {
return (
<div>
<Button variables={{ 'primaryColor': 'red' }} />
<SecondButton variables={{ 'primaryColor': 'red' }} />
<ThirdButton variables={{ 'primaryColor': 'red' }} />
</div>
);
}
如果你更喜欢创建高阶组件,你可以参考这个http://gaearon.github.io/react-dnd/但是你仍然需要正确配置你的组件来确定一些东西,比如高阶组件的道具是否应该应用.
或者,为什么不创建一个包装器组件,例如 myButton
export default class MyBytton(){
render(){
return <button { 'primaryColor': 'red' } />
}
}
render(){
return <MyButton otherProperty:"foo"/>
}
我知道您可以通过几种方式完成此任务:
扩展子道具
有限制,但允许传递 'extra' 道具来引导组件的子组件:
import React, { Component, Children } from 'react';
class Theme extends Component {
getChildren () {
const { children, variables } = this.props;
// Clone the child components and extend their props
return Children.map(children, (child) => React.cloneElement(child, {
variables
}));
}
render () {
return Children.only(this.getChildren());
}
}
// Example
<Theme variables={{ 'primaryColor': 'red' }}>
<Button />
<SecondButton />
<ThirdButton />
</Theme>
反应上下文
将变量传递到 React 树的任何部分的最简单方法是使用 React documentation 中描述的上下文(这也是确切的用例!):
// Context provider
class ThemeProvider extends Component {
getChildContext() {
return {
theme: this.props.variables
};
}
render() {
return Children.only(this.props.children);
}
}
ThemeProvider.childContextTypes = {
theme: PropTypes.object.isRequired
};
// HOC
function Theme(WrappedComponent) {
class ThemeWrapper extends Component {
render() {
return <WrappedComponent { ...this.props } />;
}
}
ThemeWrapper.contextTypes = {
theme: PropTypes.object.isRequired
};
return ThemeWrapper;
};
// Using the HOC
class Button extends Component {
render () {
return <button style={{ color: this.context.theme.primaryColor }} />;
}
}
const ThemeButton = Theme(Button);
// Example
<ThemeProvider variables={{ 'primaryColor': 'red' }}>
<div>
<ThemeButton />
</div>
</ThemeProvider>
Redux 商店
当你使用 Redux 时,你可以将每个需要主题的组件包装在 connect
HOC 中,并将你的主题信息存储在商店状态中。这是一种共享数据并避免上下文复杂性的简单方法:
class Button extends Component {
render () {
return <button style={{ color: this.props.theme.primaryColor }} />
}
}
const ConnectedButton = connect((state) => ({ theme: state.theme }))(Button);
// Example
// During app setup
store.dispatch(setTheme({ 'primaryColor': 'red' }));
// Later
<div>
<ConnectedButton />
</div>
希望对您有所帮助。
对于来到这里的任何人 post-hooks 发布,here is an excellent guide 关于如何通过上下文和 hooks 隐式传递 props。文章的快速摘要:
ThemeContext.js:
const ThemeContext = React.createContext({});
export const ThemeProvider = ThemeContext.Provider;
export const ThemeConsumer = ThemeContext.Consumer;
export default ThemeContext;
HomePage.js:
import {ThemeProvider} from './ThemeContext.js';
const HomePage = () => {
const handleClick = e => {};
const currentTheme = {backgroundColor: 'black', color: 'white'};
return (
<ThemeProvider value={currentTheme}>
<MyButton text='Click me!' onClick={handleClick} ... />
...
</ThemeProvider>
);
}
MyButton.js:
import React, { useContext } from 'react';
import ThemeContext from './ThemeContext';
const MyButton = ({text, onClick}) => {
const style = useContext(ThemeContext);
return <button style={style} onClick={onClick}>{text}</button>;
}
我希望能够为我的所有组件设置一个全局主题(变量集)以继承和扩展它们的默认变量。例如,我有一个 button
组件,它具有默认样式(内联 CSS),它引用一组变量,例如 primaryColor
,...我希望能够在我使用这些组件的任何地方轻松更新这些变量,而无需将它们显式传递给组件。
例如,我想要以下行为,我可以 (1) 将它们包装在一个组件中并让 primaryColor
级联到每个 Button
组件,或者 (2) 导出它高阶组件中的组件和提要更新道具等......但是,我无法使用这些方法中的任何一种。或许,有更好的方法或者...
(1)
render() {
return (
<Theme variables={{ 'primaryColor': 'red' }}>
<Button />
<SecondButton />
<ThirdButton />
</Theme>
);
}
(2)
render() {
return (
<div>
<Button />
<SecondButton />
<ThirdButton />
</div>
);
}
export default Theme(SampleComponent)
此方法有效,因为它显然已明确传递给每个组件:
render() {
return (
<div>
<Button variables={{ 'primaryColor': 'red' }} />
<SecondButton variables={{ 'primaryColor': 'red' }} />
<ThirdButton variables={{ 'primaryColor': 'red' }} />
</div>
);
}
如果你更喜欢创建高阶组件,你可以参考这个http://gaearon.github.io/react-dnd/但是你仍然需要正确配置你的组件来确定一些东西,比如高阶组件的道具是否应该应用.
或者,为什么不创建一个包装器组件,例如 myButton
export default class MyBytton(){
render(){
return <button { 'primaryColor': 'red' } />
}
}
render(){
return <MyButton otherProperty:"foo"/>
}
我知道您可以通过几种方式完成此任务:
扩展子道具
有限制,但允许传递 'extra' 道具来引导组件的子组件:
import React, { Component, Children } from 'react';
class Theme extends Component {
getChildren () {
const { children, variables } = this.props;
// Clone the child components and extend their props
return Children.map(children, (child) => React.cloneElement(child, {
variables
}));
}
render () {
return Children.only(this.getChildren());
}
}
// Example
<Theme variables={{ 'primaryColor': 'red' }}>
<Button />
<SecondButton />
<ThirdButton />
</Theme>
反应上下文
将变量传递到 React 树的任何部分的最简单方法是使用 React documentation 中描述的上下文(这也是确切的用例!):
// Context provider
class ThemeProvider extends Component {
getChildContext() {
return {
theme: this.props.variables
};
}
render() {
return Children.only(this.props.children);
}
}
ThemeProvider.childContextTypes = {
theme: PropTypes.object.isRequired
};
// HOC
function Theme(WrappedComponent) {
class ThemeWrapper extends Component {
render() {
return <WrappedComponent { ...this.props } />;
}
}
ThemeWrapper.contextTypes = {
theme: PropTypes.object.isRequired
};
return ThemeWrapper;
};
// Using the HOC
class Button extends Component {
render () {
return <button style={{ color: this.context.theme.primaryColor }} />;
}
}
const ThemeButton = Theme(Button);
// Example
<ThemeProvider variables={{ 'primaryColor': 'red' }}>
<div>
<ThemeButton />
</div>
</ThemeProvider>
Redux 商店
当你使用 Redux 时,你可以将每个需要主题的组件包装在 connect
HOC 中,并将你的主题信息存储在商店状态中。这是一种共享数据并避免上下文复杂性的简单方法:
class Button extends Component {
render () {
return <button style={{ color: this.props.theme.primaryColor }} />
}
}
const ConnectedButton = connect((state) => ({ theme: state.theme }))(Button);
// Example
// During app setup
store.dispatch(setTheme({ 'primaryColor': 'red' }));
// Later
<div>
<ConnectedButton />
</div>
希望对您有所帮助。
对于来到这里的任何人 post-hooks 发布,here is an excellent guide 关于如何通过上下文和 hooks 隐式传递 props。文章的快速摘要:
ThemeContext.js:
const ThemeContext = React.createContext({});
export const ThemeProvider = ThemeContext.Provider;
export const ThemeConsumer = ThemeContext.Consumer;
export default ThemeContext;
HomePage.js:
import {ThemeProvider} from './ThemeContext.js';
const HomePage = () => {
const handleClick = e => {};
const currentTheme = {backgroundColor: 'black', color: 'white'};
return (
<ThemeProvider value={currentTheme}>
<MyButton text='Click me!' onClick={handleClick} ... />
...
</ThemeProvider>
);
}
MyButton.js:
import React, { useContext } from 'react';
import ThemeContext from './ThemeContext';
const MyButton = ({text, onClick}) => {
const style = useContext(ThemeContext);
return <button style={style} onClick={onClick}>{text}</button>;
}