reactjs - ماهو - react ترجمة




هل يمكنك فرض مكون React على إعادة العرض دون استدعاء setState؟ (13)

لذا أعتقد أن سؤالي هو: هل تحتاج مكونات React إلى حالة من أجل إعادة العرض؟ هل هناك طريقة لإجبار المكون على التحديث عند الطلب دون تغيير الحالة؟

حاولت الإجابات الأخرى توضيح كيف يمكنك ذلك ، لكن النقطة المهمة هي أنه لا ينبغي لك ذلك. حتى الحل المتسلل لتغيير المفتاح يخطئ هذه النقطة. تتخلى قوة React عن التحكم في الإدارة يدويًا عندما يجب تقديم شيء ما ، وبدلاً من ذلك فقط تهتم بكيفية تعيين شيء ما على المدخلات. ثم توريد تيار المدخلات.

إذا كنت بحاجة إلى إعادة التقديم يدويًا ، فمن المؤكد أنك لا تفعل شيئًا صحيحًا.

لديّ كائن خارجي (للمكون) ، يمكن ملاحظته ، أريد الاستماع إليه من أجل التغييرات. عند تحديث الكائن ، ينبعث منه أحداث التغيير ، ثم أريد إعادة تقديم المكون عند اكتشاف أي تغيير.

من خلال React.render ذي المستوى React.render ، كان ذلك ممكنًا ، ولكن داخل أحد العناصر لا يعمل (الأمر المنطقي لأن طريقة render بإرجاع كائن فقط).

إليك مثال على الكود:

export default class MyComponent extends React.Component {

  handleButtonClick() {
    this.render();
  }

  render() {
    return (
      <div>
        {Math.random()}
        <button onClick={this.handleButtonClick.bind(this)}>
          Click me
        </button>
      </div>
    )
  }
}

يؤدي النقر فوق الزر إلى استدعاء this.render() داخليًا ، ولكن هذا ليس ما يؤدي فعليًا إلى حدوث العرض (يمكنك رؤية ذلك أثناء العمل لأن النص الذي أنشأته {Math.random()} لا يتغير). ومع ذلك ، إذا قمت ببساطة باستدعاء this.setState() بدلاً من this.render() ، فهو يعمل بشكل جيد.

لذا أعتقد أن سؤالي هو: هل تحتاج مكونات React إلى حالة من أجل إعادة العرض؟ هل هناك طريقة لإجبار المكون على التحديث عند الطلب دون تغيير الحالة؟


ربط التغييرات مخزن باستخدام HOC

باستخدام نمط HOC (مكون الترتيب العالي) ، يمكنك لف مكونات React لديك والحصول على تحديثات تلقائية عندما تتغير متاجرك. هذا هو نهج خفيف الوزن للغاية دون إطار.

withStores HOC التعامل مع مخزن التحديثات

import React, { Component } from 'react'

export default function(/* store1, store2, store3... */) {
  const storeArgs = Array.prototype.slice.call(arguments)
  return function(WrappedComponent) {
    return class WithStore extends Component {
      constructor(props) {
        super(props)
        this.state = {
          lastUpdated: Date.now()
        }
        this.stores = storeArgs
      }

      _onChange = () => {
        this.setState({ lastUpdated: Date.now() })
      }

      componentWillMount = () => {
        this.stores && this.stores.forEach(store => {
          // each store has a common change event to subscribe to
          store.on('change', this._onChange)
        })
      }

      componentWillUnmount = () => {
        this.stores && this.stores.forEach(store => {
          store.off('change', this._onChange)
        })
      }

      render() {
        return <WrappedComponent 
                 lastUpdated={this.state.lastUpdated}
                 {...this.props}  />
      }
    }
  }
}

كيف تستعمل

import React, { Component } from 'react'
import { View, Text, Button } from 'react-native'
import withStores from './withStores'
import userStore from './stores/users'

class MyView {
  _increaseUserCount = () => {
    userStore.setState({ userCount: userStore.state.count + 1 })
  }

  render() {
    return (
      <View>
        <Text>User count: {userStore.state.count}</Text>
        <Button
          title="Increase User Count"
          onPress={this._increaseUserCount}
        />
      </View>
    )
  }
}

return withStores(userStore)(MyView)

مثال بسيط فئة المتجر

var ee = require('event-emitter')
export default class Store {
  constructor() {
    this._state = {}
    this._eventEmitter = ee({})
  }
  get state() {
    return this._state
  }
  setState(newState) {
    this._state = {...this._state, ...newState}
    this._eventEmitter.emit('change')
  }
  on(ev, fn) {
    this._eventEmitter.on(ev, fn)
  }
  off(ev, fn) {
    this._eventEmitter.off(ev, fn)
  }
}

تخزين المثال على سبيل المثال

import Store from './Store'

const myStore = new Store()
export default myStore

هذا يعني حقًا للمشاريع الصغيرة ذات الأشجار المنخفضة العمق. السبب في ذلك هو أنك إذا استخدمت هذا لشجرة أكبر من المكونات ، فهذا ليس انتقائيًا للغاية بشأن الأجزاء التي يجب تحديثها لمتجر ، فقط يقوم المتجر نفسه بتشغيل التحديث.

سوف تكون على ما يرام إذا قمت بتقسيم متاجرك بطريقة أكثر حبيبة ولكن مرة أخرى ، وهذا هو السبب في أن عملية إعادة التكسير جيدة لأنها يمكن أن تكون محببة حسب الحاجة وتتطلب فقط متجرًا واحدًا ولكن تحتوي أيضًا على قاعدة ملولبة غير متناسبة في مشروع أصغر.


ES6 - أنا بما في ذلك مثال ، كان مفيدًا لي:

في "عبارة if قصيرة" يمكنك تمرير وظيفة فارغة مثل هذا:

isReady ? ()=>{} : onClick

يبدو أن هذا هو النهج الأقصر.

()=>{}

ForceUpdate () ، لكن في كل مرة أسمع فيها شخصًا يتحدث عن ذلك ، تمت متابعته معك ويجب ألا تستخدم هذا أبدًا.



في الواقع ، forceUpdate() هو الحل الصحيح الوحيد لأن setState() قد لا يؤدي إلى إعادة تقديم إذا تم تطبيق منطق إضافي في shouldComponentUpdate() أو عندما يعود ببساطة false .

تحديث بالقوة()

forceUpdate() استدعاء forceUpdate() إلى render() ليتم استدعاؤه على المكون ، مع تخطي shouldComponentUpdate() . forceUpdate()

setState ()

setState() دائمًا بتشغيل إعادة تقديم ما لم يتم تنفيذ منطق التقديم الشرطي في shouldComponentUpdate() . more...

يمكن استدعاء forceUpdate() من داخل المكون الخاص بك عن طريق this.forceUpdate()


للتأكد من اكتمالها ، يمكنك أيضًا تحقيق ذلك في المكونات الوظيفية:

 const [, updateState] = useState(); const forceUpdate = useCallback(() => updateState({}), []); // ... forceUpdate(); 

أو ، باعتبارها ربط قابلة لإعادة الاستخدام:

 const useForceUpdate = () => { const [, updateState] = useState(); return useCallback(() => updateState({}), []); } // const forceUpdate = useForceUpdate(); 

انظر: https://.com/a/53215514/2692307

يرجى ملاحظة أن استخدام آلية تحديث القوة لا يزال ممارسة سيئة لأنها تتعارض مع عقلية الرد ، لذلك يجب تجنبها إن أمكن.


مجرد رد آخر لدعم الإجابة المقبولة :-)

forceUpdate() لا يشجع استخدام forceUpdate() لأن لديهم عمومًا أسلوب "هذا هو الطريقة الوحيدة للقيام بذلك" تجاه البرمجة الوظيفية. هذا جيد في كثير من الحالات ، لكن العديد من مطوري React يتمتعون بخلفية OO ، وبهذا النهج ، من الجيد تمامًا الاستماع إلى كائن يمكن ملاحظته.

وإذا قمت بذلك ، فمن المحتمل أن تعرف أنه يجب إعادة forceUpdate() عند "الحرائق" القابلة للملاحظة ، وبالتالي ، يجب عليك استخدام forceUpdate() وهي بالفعل علامة زائد لا shouldComponentUpdate() أن يكون shouldComponentUpdate() مشتركًا فيها هنا.

أدوات مثل MobX ، التي تتبنى أسلوب OO ، تقوم فعليًا بذلك أسفل السطح (في الواقع ، تعرض مكالمات MobX render() مباشرةً)


هناك طريقة أخرى هي استدعاء setState ، والحفاظ على الحالة:

this.setState(prevState=>({...prevState}));


هناك عدة طرق لإعادة تقديم المكون الخاص بك:

الحل الأبسط هو استخدام طريقة forceUpdate ():

this.forceUpdate()

حل آخر هو إنشاء مفتاح غير مستخدم في الحالة (nonUsedKey) واستدعاء وظيفة setState مع تحديث هذا nonUsedKey:

this.setState({ nonUsedKey: Date.now() } );

أو أعد كتابة الحالة الحالية:

this.setState(this.state);

تغيير الدعائم كما يوفر rerender المكون.


يمكنك استخدام forceUpdate () لمزيد من التفاصيل ، تحقق ( forceUpdate() ).


يمكنك فعل ذلك بعدة طرق:

1. استخدم طريقة forceUpdate() :

هناك بعض الثغرات التي قد تحدث عند استخدام طريقة forceUpdate() . أحد الأمثلة هو أنه يتجاهل الأسلوب shouldComponentUpdate() طريقة العرض بغض النظر عما إذا كان shouldComponentUpdate() بإرجاع false. وبسبب هذا باستخدام forceUpdate () يجب تجنبه عند الإمكان.

2. تمرير this.state إلى الأسلوب setState()

سطر التعليمات البرمجية التالي يتغلب على المشكلة في المثال السابق:

this.setState(this.state);

حقًا كل ما يفعله هذا هو استبدال الحالة الحالية بالحالة الحالية التي تؤدي إلى إعادة عرض. لا يزال هذا ليس بالضرورة أفضل طريقة لفعل الأشياء ، لكنه يتغلب على بعض مواطن الخلل التي قد تواجهها باستخدام طريقة forceUpdate ().


forceUpdate(); ستعمل الطريقة لكن من المستحسن استخدام setState();







react-jsx