有点背景...
我正在用React创建一个应用程序(运行良好),但是对必须保留在父组件中的状态/功能数量感到沮丧。
我想做的是将某些状态和功能推送到子父组件,从而使其更易于管理。
我遇到问题的一个功能领域是Modal
组件,该组件需要在父组件的JSX中呈现。
我已将此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
我认为该功能似乎可以传递给子组件。但是我无法使用父组件中的参数。
如果您需要更多详细信息,请告诉我。
谢谢:)
答案 0 :(得分:1)
问题出在openModal和closeModal吗?
定义如下功能:
openModal = () => {
this.setState({
modalOpen: true
});
}
然后将其作为道具传递
click={() => this.openModal()}
说明
我编写函数的方式实际上等同于编写这样的函数
constructor() {
this.openModal = this.openModal.bind(this)
}
openModal() {
this.setState({modalOpen: true})
}
区别是我使用了粗箭头功能。
您可以像这样this.openModal()
然后,您必须将函数作为道具传递。如果将其作为this.openModal
传递,则子组件将无法访问父状态,但是如果将其作为() => this.openModal()
传递,则在传递函数之前先计算该函数的效果,这应该可以工作。这种传递函数的方式也适用于Angular。
更新
此功能
getClickedItem(item, category) {
console.log("[click from parent component]", arguments);
return arguments
};
参数未定义。
此外,您的openModal函数接受三个论点,但您都不通过。
实际上,您的代码看起来像是不能按原样工作。...但是,是的,将函数props作为胖箭头函数传递
工作-我已经大大更改了您的代码
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);