0

I'm constructing an object, and only one of its properties should be changed by according to another value, so a switch would be ideal, but I can't put a switch inside the initialization of the object. I know it's probably something fairly easy, but I'm new to JS.

class DegreesCircle extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            type: this.props.type,
            degrees: this.props.degrees
        }
    }

    render() {
        let circleStyle = {
            position: "relative",
            left: "50%",
            top: "45%",
            transform: "translate(-50%, 0)",

            //I need this to change according to this.props.type
            //I'd put a switch in here if I could
            borderColor: "a value",
            borderStyle: "solid",
            borderWidth: "0.5vh",
            borderRadius: "50%",
            width: "20vh",
            height: "20vh",
        }

How would I change only the borderColor property of circleStyle?

EDIT: I am not looking to put the switch in front or something. I am looking into changing one property of an object.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
SwagiWagi
  • 411
  • 5
  • 17
  • how many possible values do you have for that BorderColor? Why not store them in an object using types as keys and then you just access the key within the CircleStyle object... check my answer below. – Mosia Thabo Apr 05 '20 at 03:25

9 Answers9

1

You can use spread syntax

 let circleStyle = {
        position: "relative",
        left: "50%",
        top: "45%",
        transform: "translate(-50%, 0)",
        borderStyle: "solid",
        borderWidth: "0.5vh",
        borderRadius: "50%",
        width: "20vh",
        height: "20vh",
    }


switch (this.props.type) {
case x: 
  circleStyle = {
      ...circleStyle,
      borderColor: value,
  }
  break;
case y:
  ....
iamhuynq
  • 5,357
  • 1
  • 13
  • 36
  • 1
    why not just... `case x: circleStyle.borderColor = value; break;`? there's no need to use spread syntax here (FYI, it's [not an operator](https://stackoverflow.com/a/44934830/1541563)) – Patrick Roberts Apr 05 '20 at 03:15
  • I know, but he's asking for changing only one property of an object so I think it's about spread operator :/ – iamhuynq Apr 05 '20 at 03:16
  • @iamhuynq— `...` is a punctuator that is used in spread syntax, it is not an operator. – RobG Apr 05 '20 at 03:25
0

You can use a ternary operator like this:

    let circleStyle = {
        position: "relative",
        left: "50%",
        top: "45%",
        transform: "translate(-50%, 0)",
        borderColor: this.props.type ? 'someValue' : 'otherValue',
        borderStyle: "solid",
        borderWidth: "0.5vh",
        borderRadius: "50%",
        width: "20vh",
        height: "20vh",
    }

If you have more than two values you can define a function that returns a string based on the condition:

const getBorderColor = () => {
 switch(this.props.type) {
  case 'a':
   return 'someColor';
  case 'b':
   return 'otherColor';
  default:
   return 'defaultColor';
 }
}

and use it like:

let circleStyle = {
    position: "relative",
    left: "50%",
    top: "45%",
    transform: "translate(-50%, 0)",
    borderColor: getBorderColor(),
    borderStyle: "solid",
    borderWidth: "0.5vh",
    borderRadius: "50%",
    width: "20vh",
    height: "20vh",
}

Using spread(...) and creating a new object every time might be inefficient so this is also a good way to solve your issue.

Ramesh Reddy
  • 10,159
  • 3
  • 17
  • 32
  • Unfortunately, it is more than 2 values. – SwagiWagi Apr 05 '20 at 03:11
  • What are those values? – Ramesh Reddy Apr 05 '20 at 03:11
  • What do you mean? this.props.type may be "a" may be "b" and may be "c" so I can't use ternary. – SwagiWagi Apr 05 '20 at 03:12
  • @SwagiWagi you're not making sense. You need to at least provide the base line for this. how many values and how are you storing those values? – Mosia Thabo Apr 05 '20 at 03:23
  • @MosiaThabo She's clear to me. The values are passed as props(`this.props.type`). – Ramesh Reddy Apr 05 '20 at 03:25
  • 1
    No the types are passed via properties but the values are not. The types only tells you which color to pick. But we need to know how the collors are store. Are they in a form of a list or ? because You can do whit simply using an object with calues = {type: color} and by calling values[type] you can get the value without having to do switch statements and all that stuff – Mosia Thabo Apr 05 '20 at 03:26
0

You can use the spread command ... to merge the objects:

let circleStyle = { // base styles
  position: "relative",
  left: "50%",
  top: "45%",
  transform: "translate(-50%, 0)"
}
if (true) { // insert condition
  circleStyle = { ...circleStyle,
    borderColor: "a value",
    borderStyle: "solid",
    borderWidth: "0.5vh",
    borderRadius: "50%"
  }
}
console.log(circleStyle);
ariel
  • 15,620
  • 12
  • 61
  • 73
0

You can write the switch before object initialization.

render(){
  let borderColor = '';
  switch(this.state.type){
     case "TYPE_A": borderColor = 'red';break;
     case "TYPE_B": borderColor = 'blue';break;
     default: borderColor = 'green';break;
  }
  // then use it in the object
   let circleStyle = {
        position: "relative",
        left: "50%",
        top: "45%",
        transform: "translate(-50%, 0)",
        borderColor,
        //rest of the attributes
     }
     //rest of the render()

 }
user54321
  • 622
  • 6
  • 18
0

do it before the creating the object and later assign to the attribute you want;

let borderClr;
switch (this.props.type) {
  case 'val1':
    borderClr = 'someThing'
    break;
  case 'val2':
    borderClr = 'someThingELSE'
    break;

  default:
    break;
}


let circleStyle = {
  position: "relative",
  left: "50%",
  top: "45%",
  transform: "translate(-50%, 0)",
  borderColor: borderClr,
  borderStyle: "solid",
  borderWidth: "0.5vh",
  borderRadius: "50%",
  width: "20vh",
  height: "20vh",
}
Mechanic
  • 5,015
  • 4
  • 15
  • 38
0

I can't think of any other way simpler than this, if you values are not many and they are defined somewhere.

//Why not do this?

var PossibleValues = {
  type1 : value1,
  type2 : value2
};

//Then
let circleStyle = {
    position: "relative",
    left: "50%",
    top: "45%",
    transform: "translate(-50%, 0)",
    //  You just get the value by calling it's key
    borderColor: possibleValues[this.state.type],
    borderStyle: "solid",
    borderWidth: "0.5vh",
    borderRadius: "50%",
    width: "20vh",
    height: "20vh",
}
Mosia Thabo
  • 4,009
  • 1
  • 14
  • 24
0

I ended up setting the value like this:

        switch (this.state.type) {
            case (type.A):
                circleStyle.borderColor = "#ff3863";
                break;
            case (type.B):
                circleStyle.borderColor = "#000000";
                break;
            case (type.C):
                circleStyle.borderColor = "#000000";
                break;
            default:
                circleStyle.borderColor = "#000000";
                break;
        }

It is exactly what I was looking for, changing only one property of an object:

circleStyle.borderColor = "#000000";
SwagiWagi
  • 411
  • 5
  • 17
  • This is the longest way. Can you please check my answer? – Mosia Thabo Apr 05 '20 at 03:36
  • is type an object? since you're accessing type.A, type.B? – Mosia Thabo Apr 05 '20 at 03:39
  • @MosiaThabo That is indeed a good way of doing that, I might be using that but it does not answer my question, on how to change only one property of an object which is why I am going to accept my answer as the correct one. – SwagiWagi Apr 05 '20 at 15:19
  • Cool, But didn't you know by using . operator in an object allows you to access each property by name in an object? But to me it seems like that was your breakthrough? – Mosia Thabo Apr 05 '20 at 16:49
  • lol Ok, so you didn't know. Cool, Don't get me wrong, People post questions expecting answers and when a lot of these other guys propose solutions and I am refering to the same solutions as yours and tend to do exactly what they did as your own solutions simply isn't good enough to attribute people helping. It's just not How Stack Overflow operates. Because you're simply repeating their answers in your own fashion. Anyways, I am happy for you, Good Luck! – Mosia Thabo Apr 05 '20 at 17:14
0

There are multiple ways you can go about this, here is an examples about how you can implement this, in summary the implementation here uses an object as a Hash to return the value of the the hash using the type as key.

    class Circle { // extends React.Component.
            constructor(props = {}) {
              this.props = props; 
            }
        
            render() {
                let circleStyle = {
                    position: "relative",
                    left: "50%",
                    top: "45%",
                    transform: "translate(-50%, 0)",
        
                    //I need this to change according to this.props.type
                    //I'd put a switch in here if I could
                    borderColor: this.borderColor[ this.props.type ] || 'default',
                    borderStyle: "solid",
                    borderWidth: "0.5vh",
                    borderRadius: "50%",
                    width: "20vh",
                    height: "20vh",
                }
                
                console.log( circleStyle.borderColor );
            }

            get borderColor() {
               return {
                  'type_a': 'red',
                  'type_b': 'blue',
                  'type_c': 'green',
               }
            }
        } 
      
        // default value
        const circle_1 = new Circle({});
        circle_1.render();
        // red
        const circle_2 = new Circle({ type: 'type_a' });
        circle_2.render();
        // blue
        const circle_3 = new Circle({ type: 'type_b' });
        circle_3.render();
        // green
        const circle_4 = new Circle({ type: 'type_c' });
        circle_4.render();

In the example above if the type is not defined, 'default' value would be used instead.

Based on your original example it seems like you are using React. I would suggest to extract the styles in a separate function so your render() method gets a bit more clean, also by doing that you might be able to test that part in isolation.

const BORDR_TYPES = {
                  'type_a': 'red',
                  'type_b': 'blue',
                  'type_c': 'green',
           };
           
           
// this one extracts the type property from the properties object when generateStyles is called
// and initialize the default value to empty object when no value is passed to this function.
const generateStyles = ( { type, ...props } = {} )  => ({
                    position: "relative",
                    left: "50%",
                    top: "45%",
                    transform: "translate(-50%, 0)",
        
                    //I need this to change according to this.props.type
                    //I'd put a switch in here if I could
                    borderColor: BORDR_TYPES[ type ] || 'default',
                    borderStyle: "solid",
                    borderWidth: "0.5vh",
                    borderRadius: "50%",
                    width: "20vh",
                    height: "20vh",
})

console.log( generateStyles().borderColor );
console.log( generateStyles({ type: 'type_a' }).borderColor );
console.log( generateStyles({ type: 'type_b' }).borderColor );
console.log( generateStyles({ type: 'type_c'}).borderColor );

 

class Circle { // extends React.Component.
            constructor(props = {}) {
              this.props = props; 
            }
        
            render() {
                const circleStyle = generateStyles( this.props );
                
                console.log( circleStyle.borderColor );
            }
        }
Crisoforo Gaspar
  • 3,740
  • 2
  • 21
  • 27
0

You can use Spread syntax on objects

const circleStyle = {
  position: "relative",
  left: "50%",
  top: "45%",
  transform: "translate(-50%, 0)",
  borderColor: "a value",
  borderStyle: "solid",
  borderWidth: "0.5vh",
  borderRadius: "50%",
  width: "20vh",
  height: "20vh",
};

let prop = {
  borderStyle: "dashed",
};

let newCircleStyle = {
  ...circleStyle,
  borderStyle: prop.borderStyle || "solid",
};

console.log(JSON.stringify(newCircleStyle, null, 2));

prop = {
  // borderStyle: "dashed",
};

newCircleStyle = {
  ...circleStyle,
  borderStyle: prop.borderStyle || "solid",
};

console.log(JSON.stringify(newCircleStyle, null, 2));
Mario
  • 4,784
  • 3
  • 34
  • 50