[英]How to update child's(from the created list) props from parent
這可能涉及其他相關的一般性問題,例如如何從父級更新子級組件,盡管我想聽聽我對以下方案的設計解決方案的任何合理判斷。
我有一個父類,我在其中存儲2個子對象的css屬性。
import React from 'react'
import Item from './item/Item'
class Small_gallery extends React.Component {
constructor(props) {
super(props);
this.state = {
chosenVal: 0,
};
this.listObjParams = [
// Style 1
{
left: 300,
zIndex: 0
},
//Style 2
{
left: 320,
zIndex: 1
}
];
this.handleClick = this.handleClick.bind(this);
this.calculateShift = this.applyNewStyle.bind(this);
this.listItems = this.listObjParams.map((objStyle, i) =>
<Item
key={i}
id={i}
objStyle={objStyle}
onClick={this.handleClick}
/>
);
}
handleClick = (indexFromChild) => {
this.setState({chosenVal: indexFromChild});
this.applyNewStyle(indexFromChild)
};
applyNewStyle = (clickedIndex) => {
if (clickedIndex === 0) {
// somehow I want to apply new css style 2 to the clicked? <Item> child
};
render() {
return (
<div>
{this.listItems}
</div>
)
}
子組件相當瑣碎:
class Item extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div
onClick={(e) => {
e.preventDefault();
this.props.onClick(this.props.id)
}}
style={{
left: this.props.objStyle.left,
zIndex: this.props.objStyle.zIndex
}}
>
</div>
);
}
}
問題是:如何將樣式1或樣式2應用於單擊的Item組件(取決於我要返回的索引)? 我已經閱讀了有關getDerivedStateFromProps
而不是在這里使用不推薦使用的componentWillReceiveProps
https://hackernoon.com/replacing-componentwillreceiveprops-with-getderivedstatefromprops-c3956f7ce607,但這不是我的解決方案。
我預計創建的項目數將來會增長到10-20,因此在創建項目時用this.listObjParams
填充項目狀態是沒有意義的,或者我在這里錯了嗎?
對於<Item/>
您可以使用簡單的功能組件。 最適合簡單而不是那么復雜的用例。
例如
const Item = ({ id, clickHandler, objStyle }) => (
<div
onClick={e => {
e.preventDefault();
clickHandler(id);
}}
style={...objStyle}
/>
);
PureComponent
也將根據道具變更進行更新。
在完整類的組件中,您可以使用shouldComponentUpdate()
強制更改道具更改。 無需使用getDerivedStateFromProps
復制數據(進入狀態)(取決於用例)。
搜索一些教程(例如典型的待辦事項示例),因為您不了解狀態管理,更新等。
配售listObjParams
以外的state
也不會強迫重新描繪上更新。 順便說一句,它看起來更像是一個樣式池-也許您應該有一個子params數組...您可以將其與樣式索引數組結合使用,也可以分別保留它們(並作為道具傳遞)。
constructor(props) {
super(props);
this.state = {
// chosenVal: 0, // temporary handler param? probably no need to store in the state
listObjStyles: [0, 1] // style indexes
};
this.stylePool = [
// Style 1
{
left: 300,
zIndex: 0
},
//Style 2
{
left: 320,
zIndex: 1
}
];
用法:
this.listItems = this.state.listObjStyles.map((styleIndex, i) => <Item
key={i}
id={i}
objStyle={this.stylePool[ styleIndex ]}
clickHandler={this.handleClick}
/>
更新listObjStyles
( setState()
)將強制重新渲染,而不會更新this.stylePool
(如果需要重新渲染,則移動到該state
)。
當然, stylePool
可以為不同的項目“狀態”包含2種以上的樣式。 您可以為選定的,喜歡的,與眾不同的樣式制作樣式-通過將索引存儲在數組中,可以將它們中的任何一種與自定義邏輯混合(僅選擇一個,很多喜歡)。
10-20個項目不是您需要特殊優化(避免避免不必要的重新渲染)的情況。
我在下面有一個工作示例,以便介紹我所做的事情:
<Item />
。 activeStyles || inactiveStyles
activeStyles || inactiveStyles
是基於與對象ID(來自數組prop = items
)匹配的currentId
。 import React from "react";
const inactiveStyles = {
left: 300,
zIndex: 0,
backgroundColor: "#E9573F"
};
const activeStyles = {
left: 320,
zIndex: 1,
backgroundColor: "#00B1E1"
};
const inboundItems = [
{
id: 0
},
{
id: 1
},
{
id: 2
}
];
// Note - added to show it working not needed
const defaultStyles = {
display: "block",
border: "1px solid black",
width: 50,
height: 50
};
export const Item = ({ id, onClick, style }) => (
<>
<pre>{JSON.stringify({ styles: style }, null, 2)}</pre>
<div
{...{ id }}
style={{ ...defaultStyles, ...style }}
onClick={e => {
e.preventDefault();
onClick(id);
}}
/>
</>
);
export const SmallGallery = ({ items = inboundItems }) => {
const [currentId, setCurrentId] = React.useState(null);
const getStyles = selectedId => {
return currentId === selectedId ? activeStyles : inactiveStyles;
};
return items.map(({ id, ...item }) => (
<Item
key={id}
{...{ id }}
{...item}
style={getStyles(id)}
onClick={selectedId => setCurrentId(selectedId)}
/>
));
};
export default SmallGallery;
讓我知道您的想法,我添加了一個屏幕截圖以顯示要添加的樣式。
總結一下我所做的所有工作,基於兩個答案(仍然是一個相當有趣的示例):
家長:
import Item from './item/Item'
class Small_gallery extends React.Component {
constructor(props) {
super(props);
this.state = {
listObjStyles: [0, 1]
};
this.stylePool = [
{
position: 'absolute',
width: 600,
left: 300,
height: 100,
backgroundColor: '#000',
zIndex: 0,
transition: 'all 1s ease'
},
{
position: 'absolute',
width: 600,
left: 720,
height: 350,
backgroundColor: '#ccc',
zIndex: 1,
transition: 'all 2s ease'
}]
}
handleClick = (indexFromChild) => {
console.log(indexFromChild)
if (indexFromChild === 0) {
this.setState({
listObjStyles: [1, 0]
})
} else if (indexFromChild === 1) {
this.setState({
listObjStyles: [0, 1]
})
}
}
render() {
return (
<>
<div style={{display: 'flex', margin: 40}}>
{this.state.listObjStyles.map((styleIndex, i) =>
<Item
key={i}
id={i}
objStyle={this.stylePool[styleIndex]}
onClick={this.handleClick}
/>
)}
</div>
</>)
}
}
兒童:
const Item = ({id, onClick, objStyle}) => (
<div
onClick={e => {
e.preventDefault();
onClick(id)
}}
style={{...objStyle}}
/>
);
export default Item
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.