اذهب إلى المحتوى

السؤال

نشر

كيف يمكنني أن أستخدم document.getElementById في مكونات React حيث يظهر لي الخطأ التالي عند إستعمالها:

TypeError: document.getElementById(...) is null

هذا هو الكود الخاص بي:

var Progressbar = React.createClass({
    getInitialState: function () {
        return { finished: this.props.finished };
    },
  
    addPrecent: function (value) {
        this.props.finished += value;
        this.setState({ finished: this.props.finished });
    },

    render: function () {
        var finished = this.props.finished;
        if (finished < 0) { finished = 0 };
      
      // هنا يتم عمل مكون Progress bar ولم أقم بإرفاق الكود لعدم أهميته في المشكلة
        return (...);
    }

// المكون الرئيسي / الأب
var App = React.createClass({      
    handleClick: function (e) {
      // هذا هو السطر الذي يسبب المشكلة السابقة
        document.getElementById('Progress').addPrecent(10);
    },
    render: function () {
        return (
            <div class="center">
            	<Progressbar completed={25} id="Progress" />
            	<input type="button" onClick={this.handleClick} value="+10" />
            </div>
        )
    }
});

 

Recommended Posts

  • 0
نشر

مرحباً بك : 
أنت هنا تبحث عن عنصر ذو id = Progress أنت قمت فقط بتمرير ال id إلى المكون Progressbar ولكن لم تستخدمه وتعطيه لعنصر في ال DOM 

الحل: 

  1. Progressbar: ليس عنصر في ال DOM حتى يفهم ال id مباشرة
  2. بعد تمرير ال id يجب استخدامه على أحد عناصر ال html كالآتي
    var Progressbar = React.createClass({
        getInitialState: function () {
            return { finished: this.props.finished };
        },
      
        addPrecent: function (value) {
            this.props.finished += value;
            this.setState({ finished: this.props.finished });
        },
    
        render: function () {
            var finished = this.props.finished;
            if (finished < 0) { finished = 0 };
          
          // هذا أهم جزء لحل المشكلة بحيث تستخدم الخاصية هنا
            return (
               // تستخدم الخاصية هنا
              <div id={this.props.id}>
              	I have an id 
              </div>
            );
        }

     

  • 0
نشر

أراك تستعمل React.createClass فلماذا؟ هذا التابع قديم جداً وموجود فقط لدعم ES5 التي عفا عليها الزمان من وقت طويل.

بالنسبة لما تريد فعله فيجب استعمال ref وليس document.getElementById وذلك ﻷن document.getElementById يجلب عنصر html بينما ما تريده أنت هو reference على ProgressBar component ﻷنك تريد استدعاء addPercent method منها.

يمكن تحقيق ما تريد بالكود التالي:

class ProgressBar extends React.Component
{
    constructor() {
      	this.state = {
          finished: this.props.finished
        };
    },
  
    addPrecent(value) {
        this.setState({ finished: this.state.finished + value });
    },

    render() {
        let finished = this.state.finished;
        if (finished < 0) { finished = 0 };
      
      // هنا يتم عمل مكون Progress bar ولم أقم بإرفاق الكود لعدم أهميته في المشكلة
        return (...);
    }

// المكون الرئيسي / الأب
class App extends React.Component
{      
    constructor(){
        this.progressBarRef = React.createRef();
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick(){
        this.progressBarRef.addPrecent(10);
    },
    render() {
        return (
            <div class="center">
            	<ProgressBar ref={this.progressBarRef} finished={25} id="Progress" />
            	<input type="button" onClick={this.handleClick} value="+10" />
            </div>
        )
    }
});

باستعمال ref نضمن وصولنا إلى component instance وفي حال استعملناها على عنصر html عادي فإننا نضمن وصولنا إلى html element لنقوم بعمل focus عليه مثلاً وإلخ ولكن انتبه أن this.progressBarRef سيكون undefined حتى يتم عمل render للـProgressbar أو عنصر html أو أياً كان الذي وضعت ref عليه.

طبعاً لاحظت أنني ألغيت التعديل على props، لا يجوز بتاتاً التعديل على props الممرر من قبل اﻷب أبداً وإنما تضعها ضمن state وتعدل عليها أو تدع اﻷب يعدل عليها.

طبعاً يمكن تحقيق ما تريده بشكل أسهل من دون ref هكذا:

class ProgressBar extends React.Component
{
    render(){
        let finished = this.props.finished;
        if (finished < 0) { finished = 0 };
      
      // هنا يتم عمل مكون Progress bar ولم أقم بإرفاق الكود لعدم أهميته في المشكلة
        return (...);
    }

// المكون الرئيسي / الأب
class App extends React.Component
{
    constructor(){
        this.handleClick = this.handleClick.bind(this);
        this.state = {
          finished: 25
        }
    }
    handleClick() {
      this.setState({finished: this.state.finished + 10})
    },
    render() {
        return (
            <div class="center">
            	<ProgressBar finished={this.state.finished} />
            	<input type="button" onClick={this.handleClick} value="+10" />
            </div>
        )
    }
});

إذاً استعمال document.getElementById خاطئ في React ؟ لا ليس خاطئاً ولكنه لا ينطبق على حالتك هذا كل ما في اﻷمر.

أرجو منك ألا تستعمل createClass من جديد ﻷن الزمان عفا عليه منذ زمن طويل.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...