javascript - React - 从父级到子级访问函数参数

标签 javascript reactjs

一些背景...

我正在使用 React 创建一个应用程序(效果很好),但对必须保留在父组件中的状态/函数数量感到沮丧。

我想做的是将一些状态和功能推送到子父组件,使其更易于管理。

我遇到问题的一个功能领域是需要在父组件的 JSX 中呈现的 Modal 组件。

Modal 我已使其可重用,因此它仅呈现 {this.props.children}。内容由 switch case 语句决定,并根据其“模式”显示新组件的内容

问题...

不确定 React 中是否有这样的模式,但我想将一个函数及其参数通过 props 传递给另一个子组件,并让子组件将参数设置为渲染时的状态。

这是代码的简化版本,仅显示 1 个模态“模式/内容选项”:

import React, { Component } from "react";
import ReactDOM from "react-dom";

class Items extends Component {
    state = {
        categories: [
            {
                id: 1,
                name: "category 1",
                items: [
                    { name: "item 1", id: Math.floor(Math.random() * 99999) },
                    { name: "item 2", id: Math.floor(Math.random() * 99999) }
                ]
            },
            {
                id: 2,
                name: "category 2",
                items: [
                    { name: "item 3", id: Math.floor(Math.random() * 99999) },
                    { name: "item 4", id: Math.floor(Math.random() * 99999) }
                ]
            },
            {
                id: 3,
                name: "category 3",
                items: [
                    { name: "item 5", id: Math.floor(Math.random() * 99999) }
                ]
            }
        ],
        modalOpen: true,
        modalMode: ""
    };

    getClickedItem(item, category) {
        console.log("[click from parent component]", arguments);
        return arguments
    };

    openModal(mode, item, category) {
        if (mode === "editItem") {
            this.getClickedItem(item, category);
        }
        this.setState({
            modalOpen: true,
            modalMode: mode
        });
    }

    closeModal() {
        this.setState({
            modalOpen: false,
            modalMode: ""
        });
    }
    render() {
        const { categories, modalOpen, modalMode } = this.state;

        let modalContent;

        switch (modalMode) {
            case "editItem":
                modalContent = (
                    <Component1 closeModal={this.closeModal.bind(this)} getClickedItem={this.getClickedItem}/>
                );
                break;
            default:
                break;
        }

        return (
            <div>
                {categories.map(cat => {
                    return (
                        <ItemCategory
                            {...cat}
                            key={cat.id}
                            click={this.openModal.bind(this)}
                        />
                    );
                })}
                <Modal show={modalOpen}>{modalContent}</Modal>
            </div>
        );
    }
}

class ItemCategory extends Component {
    handleClick(item, category) {
        this.props.click("editItem", item, category);
    }
    render() {
        const { items, name } = this.props;

        const getItems = items.map(item => {
            return item;
        });

        return (
            <div>
                <div>-{name}</div>
                <ul>
                    {getItems.map(item => {
                        return (
                            <li
                                key={item.id}
                                onClick={() => this.handleClick(item, name)}
                            >
                                {item.name}
                            </li>
                        );
                    })}
                </ul>
            </div>
        );
    }
}

class Component1 extends Component {
    state = {
        item: "",
        category: ""
    }

    static getDerivedStateFromProps(props, state) {
        const getParams = props.getClickedItem()
        console.log("[from child component]", getParams)
    }

    render() {
        const { item, category } = this.state;
        const { closeModal } = this.props;

        return (
            <div>
                <h1>Component1 modal content</h1>
                <button onClick={closeModal}>Close</button>
                {item}
                {category}
            </div>
        );
    }
}

class Modal extends Component {
    render() {
        return (
            <div
                style={{
                    transform: this.props.show
                        ? "translateY(0)"
                        : "translateY(-100vh)",
                    opacity: this.props.show ? "1" : "0"
                }}
            >
                {this.props.children}
            </div>
        );
    }
}

function App() {
    return <Items />;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

也可用作代码笔 https://codesandbox.io/s/m7jm5z0w4j

我认为该函数似乎可以很好地传递给子组件!但我无法使用父组件的参数。

任何对此的见解都会很棒,如果您需要更多详细信息,请告诉我。

谢谢:)

最佳答案

问题出在 openModal 和 closeModal 上吗?

定义如下函数:

openModal = () => {
    this.setState({
        modalOpen: true
    });
}

然后将其作为 prop 传递,如下所示

click={() => this.openModal()}
<小时/>

说明

我编写函数的方式实际上等同于这样编写函数

constructor() {
    this.openModal = this.openModal.bind(this)
}

openModal() {
    this.setState({modalOpen: true}) 
} 

不同之处在于我使用了粗箭头函数。

您可以像这样调用函数 this.openModal()

然后你必须将函数作为 prop 传递。如果您将其作为 this.openModal 传递,则子组件无法访问父状态,但如果您将其作为 () => this.openModal() 传递,则函数的效果是在传递之前计算的,这应该可行。这种传递函数的方式也适用于 Angular。

更新

在这个函数中

getClickedItem(item, category) {
    console.log("[click from parent component]", arguments);
    return arguments
};

参数未定义。

此外,您的 openModal 函数接受三个参数,但您没有传递任何参数。

实际上你的代码看起来不会像现在这样工作......但是,是的,将函数 Prop 作为胖箭头函数传递

<小时/>

工作 - 我相当显着地改变了你的代码

import React, { Component } from "react";
import ReactDOM from "react-dom";

class Items extends Component {
  state = {
    categories: [
      {
        id: 1,
        name: "category 1",
        items: [
          { name: "item 1", id: Math.floor(Math.random() * 99999) },
          { name: "item 2", id: Math.floor(Math.random() * 99999) }
        ]
      },
      {
        id: 2,
        name: "category 2",
        items: [
          { name: "item 3", id: Math.floor(Math.random() * 99999) },
          { name: "item 4", id: Math.floor(Math.random() * 99999) }
        ]
      },
      {
        id: 3,
        name: "category 3",
        items: [{ name: "item 5", id: Math.floor(Math.random() * 99999) }]
      }
    ],
    modalOpen: false,
    selectedItem: {}
  };
  openModal = item => {
    this.setState({
      modalOpen: true,
      selectedItem: item
    });
  };

  closeModal = () => {
    this.setState({
      modalOpen: false
    });
  };
  render() {
    const { categories, modalOpen, selectedItem } = this.state;
    return (
      <div>
        {categories.map(cat => {
          return (
            <ItemCategory
              {...cat}
              key={cat.id}
              click={item => this.openModal(item)}
            />
          );
        })}
        <Modal show={modalOpen}>
          <Component1
            closeModal={() => this.closeModal()}
            item={selectedItem}
          />
        </Modal>
      </div>
    );
  }
}

class ItemCategory extends Component {
  handleClick = item => {
    this.props.click(item);
  };
  render() {
    const { items, name } = this.props;

    const getItems = items.map(item => {
      return item;
    });

    return (
  <div>
    <div>-{name}</div>
    <ul>
      {getItems.map(item => {
        return (
          <li key={item.id} onClick={() => this.handleClick(item)}>
            {item.name}
          </li>
        );
      })}
    </ul>
  </div>
);
  }
}

class Component1 extends Component {
  render() {
    const { item, closeModal } = this.props;
    console.log(item);
    return (
      <div>
        <h1>{item.name} modal content</h1>
        <button onClick={closeModal}>Close</button>
      </div>
    );
  }
}

class Modal extends Component {
  render() {
    return (
      <div
        style={{
          transform: this.props.show ? "translateY(0)" : "translateY(-100vh)",
          opacity: this.props.show ? "1" : "0"
        }}
      >
        {this.props.children}
      </div>
    );
  }
}

function App() {
  return <Items />;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

关于javascript - React - 从父级到子级访问函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52443156/

相关文章:

javascript - wxWebView 和 JavaScript

javascript - 如何仅使用 JS(不是 jquery)更改 div 的颜色,而没有 ID 或单击元素?

javascript - 有没有人遇到过 "encodeURIComponent(string)"的跨浏览器问题

javascript - 如何与 React JS/Node JS 一起部署到 Amazon Web Services (AWS)?

javascript - 类型错误 : invalid 'in' operand a error when calling jQuery each inside RequireJS module

javascript - 需要 Discord.js 机器人帮助 - 如何让我的机器人每 6 小时自动执行一次任务而不向它发送命令?

javascript - 错误说 rowRenderer 不是函数

css - 当放置在 <head/> 标签内时,TinyMCE React 会去除 &lt;style/> 标签

javascript - 初始化前无法访问词法声明 `callback'

javascript - 在单个选项上使用 onClick 事件响应语义 UI DropDown