簡體   English   中英

如何從父級更新子級(從創建的列表中)的道具

[英]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}
    />

更新listObjStylessetState() )將強制重新渲染,而不會更新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;

讓我知道您的想法,我添加了一個屏幕截圖以顯示要添加的樣式。

<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM