首页 文章

将组件和道具作为参数传递

提问于
浏览
1

我试图基于MobX可观察值在App.js中呈现一个组件 . 我想定义一个采用组件和一些新的自定义道具分配的动作 . 这就是我现在拥有的:

// App.js inside render()
{ ui_store.main_area_sequence }

.

// ui_store.js

// OBSERVABLES / state
main_area_sequence = <ChoosePostType />;

// ACTIONS / state mutators
update_ui_in_main_section(ComponentTag, props) {
    this.main_area_sequence = <ComponentTag {props} />
}

组件参数按预期工作 . 但我不能让道具论证起作用 . 理想情况下,我会用它来构建类似的东西:

<ChildComponentToBeSwitchedIn name={ui_store.name} handleClick={this.handleClick} />

作为一个示例, <ChoosePostType /> 中的按钮可能会将 main_area_sequence 中的可观察值重新分配给上面的点击 .

有没有人知道如何将道具作业作为参数传递给他们?

2 回答

  • 1

    我怀疑你是在思考这个问题 .

    回想一下,JSX只是JavaScript . 当你输入这个:

    <Foo bar={123}>Baz!</Foo>
    

    ......你真的写这个:

    React.createElement(Foo, { bar: 123 }, 'Baz!');
    

    但是,如果要渲染的组件是动态的,该怎么办?那's fine; it still works. For example, suppose we kept the component and props in our React component' s state

    render() {
      return (
        <this.state.dynamicComponent
          {...this.state.dynamicComponentProps}
          name={this.props.name}
          onClick={this.handleClick}
        />
      );
    }
    

    上面的JSX转换为这个JavaScript:

    React.createElement(this.state.dynamicComponent,
      { ...this.state.dynamicComponentProps,
        name: this.props.name,
        onClick: this.handleClick,
      }
    );
    

    如你所见,我们从 this.state.dynamicComponentProps 获得道具,但我们也从 this.props.name 添加一个 name 道具,从 this.handleClick 添加 onClick 道具 . 您可以想象 this.handleClick 调用 this.setState 来更新 dynamicComponentdynamicComponentProps .

    实际上,您不必想象它,因为您可以在下面的代码片段中看到它:

    class DynamicComponent extends React.Component {
      constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
        this.state = {
          dynamicComponent: ShowMeFirst,
          dynamicComponentProps: { style: { color: 'blue' }},
        };
      }
      
      render() {
        return (
          <this.state.dynamicComponent
            {...this.state.dynamicComponentProps}
            name={this.props.name}
            onClick={this.handleClick}
          />
        );
      }
      
      handleClick() {
        this.updateDynamicComponent(ShowMeSecond, { style: { color: 'red' }});
      }
    
      updateDynamicComponent(component, props) {
        this.setState({
          dynamicComponent: component,
          dynamicComponentProps: props,
        });
      }
    }
    
    const ShowMeFirst = ({ name, style, onClick }) => (
      <button type="button" style={style} onClick={onClick}>
        Hello, {name}!
      </button>
    );
    
    const ShowMeSecond = ({ name, style, onClick }) => (
      <button type="button" style={style} onClick={onClick}>
        Goodbye, {name}!
      </button>
    );
    
    ReactDOM.render(<DynamicComponent name="Alice"/>, document.querySelector('div'));
    
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <div></div>
    

    我上面使用了普通的旧React状态,但是同样的东西适用于MobX,如下所示 . (我之前从未使用过MobX,所以我的代码可能不是惯用的,但希望你能得到这个想法 . )

    const { action, decorate, observable } = mobx;
    const { observer } = mobxReact;
    
    class UIStore {
      dynamicComponent = ShowMeFirst;
      dynamicComponentProps = { style: { color: 'blue' }};
      
      updateDynamicComponent(component, props) {
        this.dynamicComponent = component;
        this.dynamicComponentProps = props;
      }
    }
    
    decorate(UIStore, {
      dynamicComponent: observable,
      dynamicComponentProps: observable,
      updateDynamicComponent: action,
    });
    
    const DynamicComponent = observer(({ store, name }) => (
      <store.dynamicComponent
        {...store.dynamicComponentProps}
        name={name}
        onClick={() =>
          store.updateDynamicComponent(ShowMeSecond, { style: { color: 'red' }})
        }
      />
    ));
    
    const ShowMeFirst = ({ name, style, onClick }) => (
      <button type="button" style={{...style}} onClick={onClick}>
        Hello, {name}!
      </button>
    );
    
    const ShowMeSecond = ({ name, style, onClick }) => (
      <button type="button" style={{...style}} onClick={onClick}>
        Goodbye, {name}!
      </button>
    );
    
    ReactDOM.render(<DynamicComponent name="Alice" store={new UIStore()} />, document.querySelector('div'));
    
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/mobx/lib/mobx.umd.js"></script>
    <script src="https://unpkg.com/mobx-react@5.2.3/index.js"></script>
    <div></div>
    

    我不得不在这里使用 decorate ,因为Stack Overflow 's Babel configuration doesn' t包含装饰器,但我在CodeSandbox上发布了与装饰器相同的东西:https://codesandbox.io/s/qlno63zkw4

  • 1

    如果你没有传递道具,那么不要包含道具参数 .

    update_ui_in_main_section(ComponentTag) {
      this.main_area_sequence = <ComponentTag handleClick={this.handleClick} />;
    }
    

相关问题