componentWillReceiveProps this.props和nextProps始终相同

Gur*_*bot 5 javascript state reactjs

我有一个父组件ProductTest,它持有状态作为真​​相的来源。状态是一组变体项目。在此示例中,每个项目都经过了简化,并有一个标题。

当Variant的标题更新时,子代将通过父代传递的prop调用其处理程序回调。然后,父级将更新状态,而子级将具有新的title属性。

我所看到的是,孩子的componentWillReceiveProps功能将显示相同的值this.propsnextProps。我认为,由于值是由父级提供的,因此两者将有所不同。

我不确定自己做错了什么。

这是父产品测试组件:

import React, { Component } from 'react'
import { connect } from 'react-redux'
import axios from 'axios'
import Variant from './variants/Variant'

import { REACT_APP_API_URL, REACT_APP_SITE_KEY } from '../../../shared/vars'

import '../../../css/variants.css'

class ProductTest extends Component {
    constructor(props) {
        super(props)
        this.state = {
            variants: []
        }

        this.handleVariantTitleChange = this.handleVariantTitleChange.bind(this)
        this.handleVariantValueChange = this.handleVariantValueChange.bind(this)
    }

    componentDidMount() {
        this.loadData()
    }

    loadData() {
        const apiEndpoint = 'products/some-product'
        const AUTH_HEADER = { Authorization: REACT_APP_SITE_KEY }
        return axios.get(REACT_APP_API_URL + apiEndpoint, { headers: AUTH_HEADER })
            .then((response) => {
                this.setState({ variants: response.data.product.variants })
            })
            .catch((err) => {
                console.log("YA GOOFED BUD!", err)
            })
    }

    handleVariantTitleChange(e, i) {
        let { variants } = this.state
        const { value } = e.target

        variants = variants.map((item, index) => {
            item.title = i === index ? value : item.title
            return item
        })

        this.setState({ variants })
    }

    handleVariantValueChange(e, id) {
        let { variants } = this.state
        const { value } = e.target

        variants = variants.map(variant => {
            variant.items = variant.items.map(item => {
                item.title = id === item.id ? value : item.title
                return item
            })
            return variant
        })

        this.setState({ variants })
    }

    render() {
        return (
            <div>
                {this.state.variants.map((variant, i) => {
                    return <Variant key={i}
                        variant={variant}
                        index={i}
                        changeVariantTitle={this.handleVariantTitleChange}
                        changeVariantValue={this.handleVariantValueChange}
                    />
                })}
            </div>
        )
    }
}

export default ProductTest
Run Code Online (Sandbox Code Playgroud)

这是子Variant组件:

import React, { Component } from 'react'

class Variant extends Component {
    componentWillReceiveProps(nextProps){
        console.log(this.props, nextProps)
    }

    render() {
        const { variant, index } = this.props

        return (
            <div className="variant-wrapper" data-new="new_value">
                <div className="ajax-error" data-hbs-id="{{id}}"></div>
                <div className="varient-item-titles">
                    <div className="variant-item-title">
                        Title
                    </div>
                    <div className="varient-attribute-titles">
                        <div className="variant-attribute">Value</div>
                    </div>
                </div>
                <div className="variant-item-content">
                    <div className="variant-label">
                        <input type="text" name="variant_label" value={variant.title} placeholder="Size, colour, etc."
                            onChange={e => this.props.changeVariantTitle(e, index)}
                        />
                    </div>
                </div>
            </div>
        )
    }
}

export default Variant
Run Code Online (Sandbox Code Playgroud)

之前

在此处输入图片说明

在此处输入图片说明

Console.log()

这两个对象是this.props和nextProps。注意title属性没有变化,正如我期望的那样。

在此处输入图片说明

解!

所有这些的原因是我没有正确地不变地改变父母的状态。我想我只是在相同的内存地址上更改了值,因此到到达componentWillReceiveProps该值时,它已经是新值了。我认为...

我发现以下将起作用:

handleVariantTitleChange(e, i){
    const { value } = e.target

    // Immutably clone specific variant item
    let variant = Object.assign({}, this.state.data.variants[i])

    // Set new title to item
    variant.title = value

    // Set the variant to the cloned item
    let variants = this.state.data.variants
    variants[i] = variant

    this.setState({
        data: {
            ...this.state.data,
            variants
        }
    })
}
Run Code Online (Sandbox Code Playgroud)