1

Thanks for helping my needy butt. I am working with ReactJS and trying to get a div to change it's background from a color to a specific image url on click of a button in a modal. I have tried many things and keep getting this error:
TypeError: Cannot read property 'style' of null

I successfully console.log the image URL and div ID within the onclick function, but the div styling is getting nowhere...All help is appreciated!

Here is my button

<button onClick={() => { this.changeUserBG(this.state.AlexPics[0], "one") }} className="btn btn-danger">Kaalia of the Vast</button>

here is the function I call

  changeUserBG = (imageUrl, userArea) => {
        let thisOne = document.getElementById(userArea);
        console.log(thisOne)
        thisOne.style.backgroundColor = 'red'
        // document.getElementById("one").style.backgroundImage = `require(url(${imageUrl}))`;

    } 

Here is the div area I am trying to manipulate:


<div className="col-6" id="one">

       <div className="">

         <p className="lifeArea">
          <button className="minusOne" onClick={() => { 
              this.subtractOne("playerOne") }}>-1</button>
             <span id="playerOne">40</span>
             <button className="plusOne" onClick={() => { 
             this.addOne("playerOne") }}>+1</button>
         </p>

{/* Theme Modal that has ASK sub modals */}
<p className="bgCheckButton">
<button type="button" className="btn btn-primary" data-toggle="modal" data-target="#exampleModalScrollable">Theme</button>
</p>
</div>

wanna talk mtg? down for that too!

5
  • 1
    It looks like the div is not found while accessing its style. You must adjust the code to ensure that the div exists at that moment. Commented Jan 14, 2020 at 2:39
  • Since I am only calling the function on button click shouldn't it not check until it is clicked? Commented Jan 14, 2020 at 2:49
  • 1
    For the record, manually doing things like document.getElementById(userArea); in react code is strongly discouraged, I'd recommend looking at a react tutorial if you're new to it. Assuming you know what you're doing though - the error implies that <span id="playerOne"></span> isn't available on the page when you click the -1 button. I'd suggest verifying that it exists with dev tools before clicking it. I'd be willing to bet that it's not the div you were expecting, but a 3/3 Elk instead. Commented Jan 14, 2020 at 2:49
  • @JackFranklin If your goal is to secure the process, two options for you: 1. Disable the button until the div is added somehow. 2. Check the existence of the div in the click handler every time. Commented Jan 14, 2020 at 2:53
  • Is it possible that there is an issue with the this binding? I know that the primary advantage to using An arrow ()=> {...} over function() is that the arrow locks the this context. (But I stick by "Never expect this to be what you think this is") Commented Jan 14, 2020 at 5:26

2 Answers 2

2

In react, you should not use getElementById or any method changing the dom. You could have something like this:

<div style={{backgroundImage: this.state.image}}>...</div>

So whenever you do:

this.setState({ image: 'some_value.png' });

the background image will be updated automatically.

In your case, if you need to change different div background based on div ID, you could store a map in your state, something like this:

clickHandler = (divId, color) => {
   this.setState(state => ({ backgroundColors: { [divId]: color, ...state.backgroundColors} }));
}

The line of code above might be hard to understand at first if you are not used to the spread operator, but what it does is actually simple: it adds a new key to map backgroundColors stored in the state.

And you would use it as such:

<div id="foo" style={{ backgroundImage: this.state.backgroundColors["foo"]}}>...</div>
Sign up to request clarification or add additional context in comments.

Comments

0

You can use React ref api to get the refrence of the div and then you can change the style property of the div.

Sample Code

In Class constructor



constructor() {
  this.userAreaRef = React.createRef();
}

changeUserBG = (imageUrl, userArea) => {
  let thisOne = this.userAreaRef;
  console.log(thisOne)
  thisOne.current.style.backgroundColor = 'red'
}

Render

 <div ref={this.userAreaRef} className="col-6" id="one">
            <div className="">
                <p className="lifeArea">
                    <button className="minusOne" onClick={()=> { 
this.subtractOne("playerOne") }}>-1</button>
                    <span id="playerOne">40</span>
                    <button className="plusOne" onClick={()=> { 
this.addOne("playerOne") }}>+1</button>
                </p>
                {/* Theme Modal that has ASK sub modals */}
                <p className="bgCheckButton">
                    <button type="button" className="btn btn-primary" data-toggle="modal" data-target="#exampleModalScrollable">Theme</button>
                </p>
            </div>
        </div>

In functional component

const someFunction = () => {
  const userAreaRef = useRef();

  changeUserBG = (imageUrl, userArea) => {
    let thisOne = userAreaRef;
    console.log(thisOne)
    thisOne.current.style.backgroundColor = 'red'
  }

  return (
    <div ref={this.userAreaRef} className="col-6" id="one">
            <div className="">
                <p className="lifeArea">
                    <button className="minusOne" onClick={()=> { 
this.subtractOne("playerOne") }}>-1</button>
                    <span id="playerOne">40</span>
                    <button className="plusOne" onClick={()=> { 
this.addOne("playerOne") }}>+1</button>
                </p>
                {/* Theme Modal that has ASK sub modals */}
                <p className="bgCheckButton">
                    <button type="button" className="btn btn-primary" data-toggle="modal" data-target="#exampleModalScrollable">Theme</button>
                </p>
            </div>
        </div>
  );
}

3 Comments

What is the purpose of using a reference here ? You should not use a reference when you do not need to, this is a react principle.
I agree with you but it's not wrong, you can use React ref api. If you don't want to maintain the state. Could you share some reference where React team is mentioning that we should not use Ref
The fact that you can does not mean you should :) Here is a link to react doc: reactjs.org/docs/refs-and-the-dom.html It clearly says Avoid using refs for anything that can be done declaratively.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.