React Provider Pattern,子组件中的道具没有更新

Posted

技术标签:

【中文标题】React Provider Pattern,子组件中的道具没有更新【英文标题】:React Provider Pattern, prop not updating in child component 【发布时间】:2018-11-25 07:30:29 【问题描述】:

所以我编写了一个提供程序来将字符串传递给我的应用程序的任何部分。我遇到的问题是,如果我向我的子组件添加一个字符串道具,它会覆盖整个道具并且似乎忽略了我在连接器中所做的合并

提供者

import  Component, Children  from 'react'
import PropTypes from 'prop-types'

export default class StringsProvider extends Component 
  static propTypes = 
    children: PropTypes.element.isRequired,
    strings: PropTypes.object
  

  // Specify what is being added to context
  static childContextTypes = 
    strings: PropTypes.object.isRequired
  

  getChildContext() 
    const  strings  = this.props

    return  strings: strings 
  

  render() 
    return Children.only(this.props.children)
  

连接器

import React,  Component  from 'react'
import PropTypes from 'prop-types'
import _ from 'lodash'

// here we basically create a HOC that returns on Context (This is our component).
// The HOC adds the merged strings set to the Context Component and then renders it
export default (WrappedComp, defaultStrings, stringNameSpace) => 
  return class StringsComponent extends Component 
    static propTypes = 
      strings: PropTypes.object.isRequired
    

    static contextTypes = 
      strings: PropTypes.object.isRequired
    

    // Takes the defaultStrings from the context and merges them with the
    // strings passed to the Context Component
    getStrings = () => 
      let out

      if (this.props.strings) 

        console.log('defaultStrings: ' + Object.values(defaultStrings)[0])
        console.log(
          'this.context.strings[stringNameSpace]: ' +
            Object.values(this.context.strings[stringNameSpace])[0]
        )
        console.log(
          'this.props.strings: ' + Object.values(this.props.strings)[0]
        )
        out = _.merge(
          defaultStrings,
          this.context.strings[stringNameSpace] ? this.context.strings[stringNameSpace] : ,
          this.props.strings
        )
       else 
        out = _.merge(defaultStrings, this.context.strings[stringNameSpace])
      


      console.warn('out')
      console.log(out)
      return out
    

    render() 
      return <WrappedComp strings=this.getStrings()  ...this.props />

    
  

组件

import React,  Component  from 'react'
import  connectStrings  from './../../src'
import PropTypes from 'prop-types'
import defaultStrings from './strings'

class SampleComponent extends Component 
  static propTypes = 
    strings: PropTypes.object.isRequired
  

  render() 
    const  strings  = this.props
console.warn(strings)
    return (
      <div>
        <span>strings.str1</span>
        <span>strings.str2</span>
        <span>strings.str3</span>
      </div>
    )
  


export default connectStrings(
  SampleComponent,
  defaultStrings,
  'sampleComponent.ui.SET_TWO'
)

要运行的单元测试

import renderer from 'react-test-renderer'
import React from 'react'
import  StringProvider  from '../src'
import SampleComponent from "../components/sampleComponent";
describe('String Provider Tests', () => 
  it('should render', () => 
    const strings = 
      'sampleComponent.ui.SET_ONE': 
        str1: 'SET ONE'
      ,
      'sampleComponent.ui.SET_TWO': 
        str1: 'SP Str1',
        str2: 'SP Str2'
      
    

    const tree = renderer.create(
      <StringProvider strings=strings>
        <SampleComponent strings=str3: 'test'/>

      </StringProvider>
    )

    expect(tree).toMatchSnapshot()
  )
)

我不确定我在这里缺少什么,但字符串似乎在连接器中更新但在组件中没有更新,是不是我做错了什么?

【问题讨论】:

【参考方案1】:

多么愚蠢,答案很简单,下面我只需要更改道具在包装组件中的添加顺序

return <WrappedComp strings=this.getStrings()  ...this.props />

似乎 this.props 也包含字符串,它覆盖了 GetStrings() 函数的结果。

【讨论】:

以上是关于React Provider Pattern,子组件中的道具没有更新的主要内容,如果未能解决你的问题,请参考以下文章

为啥第二个(兄弟)React Context Provider 不起作用?或者,如果上面有同级 Context Provider,为啥 React Context Provider 不起作用

React-Router&MobX - Provider

React中的connect使用(Provider+Consumer例子 以及 contextType+this.context例子)

React-redux使用中有关Provider问题

同一 Provider 的多个声明是不是会在 React 中创建新实例?

React Context 和 Provider 数据没有按预期传递