如何基于React中另一个组件的更改来更新组件

发布时间:2020-07-07 11:04

有两个组件之间没有父子关系或兄弟姐妹关系。

其中一个构建工具栏,另一个构建一个颜色选择器。想法是根据颜色选择器中设置的值更改工具栏的颜色。

到目前为止,这是我的代码:

import React from 'react';
import { Button, Icon } from 'semantic-ui-react';
import { ChromePicker } from 'react-color';

export default class Banner extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      displayColorPicker: false,
      background: '#fff',
    };
  }

  handleClick = () => {
    this.setState({ displayColorPicker: true });
  };

  handleClose = () => {
    this.setState({ displayColorPicker: false });
  };

  handleChange = color => {
    this.setState({ background: color.hex });
  };

  handleChangeComplete = color => {
    this.setState({ background: color.hex });
  };

  render() {
    const popover = {
      position: 'absolute',
      zIndex: '2',
    };
    const cover = {
      position: 'fixed',
      top: '0px',
      right: '0px',
      bottom: '0px',
      left: '0px',
    };
    return (
      <div className="banner-container settings-banner">
        <table className="settings-banner-container">
          <tbody>
            <tr className="setttings-container-tr">
              <div
                className="xx"
                style={{ backgroundColor: this.state.background }}>
                <div className="title-cell-value settings-banner-title">
                  Brand color
                </div>
                <div>
                  <Button onClick={this.handleClick}>Pick Color</Button>
                  {this.state.displayColorPicker ? (
                    <div style={popover}>
                      <div
                        style={cover}
                        onClick={this.handleClose}
                        onKeyDown={this.handleClick}
                        role="button"
                        tabIndex="0"
                        aria-label="Save"
                      />
                      <ChromePicker
                        color={this.state.background}
                        onChange={this.handleChange}
                        onChangeComplete={this.handleChangeComplete}
                      />
                    </div>
                  ) : null}
                </div>
              </div>
            </tr>
          </tbody>
        </table>
      </div>
    );
  }
}

在上述文件中,ChromePicker用于选择颜色并将其值保存在this.state.background中。我正在使用该值用类xx更新div的颜色。效果很好,可以直接更新div的颜色。

但是,我不知道如何将该颜色值“导出”到外部并在另一个组件中使用。

在这种情况下,它应该是工具栏,我想将值从this.state.background发送到style = {{ .. }}

有办法吗?

import React from 'react';
import Logo from '../Logo/Logo';

export default class Toolbar extends React.PureComponent {
  render() {
    return (
      <div className="corporate-toolbar" style={{ backgroundColor: 'green' }}>
        <Logo corporate />
      </div>
    );
  }
}
回答1

有很多方法可以做到

您可以使用 context (最佳解决方案) redux (如果您的应用是 或只是将属性移至common parent并将其传递给组件(这是最糟糕的方式,不建议使用)

上下文文档-https://reactjs.org/docs/context.html

关于redux的文档-https://react-redux.js.org

使用上下文https://www.digitalocean.com/community/tutorials/react-usecontext

的简单示例
回答2

这是一个使用上下文的有效示例:

//in file ColorContext.js (should export but breaks snippet)
const ColorContext = React.createContext();
const ColorProvider = ({ children }) => {
  const [color, setColor] = React.useState('#fff');
  return (
    <ColorContext.Provider value={{ color, setColor }}>
      {children}
    </ColorContext.Provider>
  );
};
//in file Banner.js
class Banner extends React.PureComponent {
  handleChange = (color) => {
    this.context.setColor(color);
  };

  render() {
    return (
      <div style={{ backgroundColor: this.context.color }}>
        <select
          value={this.context.color}
          onChange={(e) =>
            this.handleChange(e.target.value)
          }
        >
          <option value="#fff">fff</option>
          <option value="#f00">f00</option>
          <option value="#f0f">f0f</option>
        </select>
      </div>
    );
  }
}
//ColorContext is imported from ColorContext.js
Banner.contextType = ColorContext;
//in file Toolbar.js
class Toolbar extends React.PureComponent {
  render() {
    return (
      <h1 style={{ backgroundColor: this.context.color }}>
        Toolbar
      </h1>
    );
  }
}
//ColorContext is imported from ColorContext.js
Toolbar.contextType = ColorContext;

const App = () => (
  <div>
    <Banner />
    <Toolbar />
  </div>
);
ReactDOM.render(
  <ColorProvider>
    <App />
  </ColorProvider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>