React component for Pai Gow game











up vote
1
down vote

favorite












TL;DR what should I do if I have too many methods in my parent component??



I'm making a card game (Pai Gow Tiles) using react and I am having trouble finding a way to format my parent component. I've always heard that you should keep your components small and mine is over 300 lines. Most of it are methods that I need for my logic to set my hand 'house-way'. Think of house way as a set of rules on how to play a hand depending on what cards you're dealt. I tried separating the methods into different files, but some methods use 'this' and it throws an error.



export default class Layout extends Component {
constructor(props) {
console.log("starting up");
super(props);
//each hand holds a randomly generated tile object from { tilesSet }
this.state = {
//needs empty spots for when (mounting) <Hands hand1={this.state.hand[0].img} /> else error since hand[0] doesnt exist.
hand: ["", "", "", ""],
cards: false,
pairName: '',
rule: '',
show: false,
history: ,
input1: 'GJ3',
input2: 'GJ6',
input3: 'teen',
input4: 'teen'
};
//binding in the constructor is recommended for performance.
this.handleToggle = this.handleToggle.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handleHW = this.handleHW.bind(this);
this.assignHands = this.assignHands.bind(this);
this.checkPair = this.checkPair.bind(this);
this.checkTeenDey = this.checkTeenDey.bind(this);
this.hiLowMiddle = this.hiLowMiddle.bind(this);
this.compare = this.compare.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.userInput1 = this.userInput1.bind(this);
this.userInput2 = this.userInput2.bind(this);
this.userInput3 = this.userInput3.bind(this);
this.userInput4 = this.userInput4.bind(this);
this.inputClick = this.inputClick.bind(this);
this.baccaratCount = this.baccaratCount.bind(this);
}

baccaratCount = (n, m) => {
//recognizing gong , wong , or pair...
let number = n.val + m.val;
if(n.rank === m.rank){
return 'Pair';
}
else if (n.val === 2 || m.val === 2){
if (number === 10){
return "Gong";
}
else if (number === 11){
return 'Wong';
}
}
//regular baccarat counting...
else if (number >= 10 && number < 20){
if (number >= 20) {
return number -= 20;
}
return number -= 10;
}
//value is under 10, return the sum.
return number;
}

//n = pairTL, n2 = otherTL
split(n, n2){
//Gee Joon
if (n[0].pair === 1) {
let combo1 = this.baccaratCount(n2[0], n[0]);
let combo2 = this.baccaratCount(n2[1], n[1]);
//if it meets the split requirements...
if((combo1 >= 7 && combo2 >= 9) || (combo1 >= 9 && combo2 >= 7)){
console.log('got em', combo1, combo2);
return true;
}
else {

return true;
}
}
}

//checks for pairs. takes an array as arg
checkPair(hand){
for(let i = 0; i < hand.length; i++) {
for (let ii = 0; ii < hand.length; ii++) {
// if there is a pair and it is not comparing to itself.
if (hand[i].pair === hand[ii].pair && i !== ii) {
let pairTL = hand.filter((x) => x.rank === hand[i].rank); //array of the pair tiles
let otherTL = hand.filter((x) => x.rank !== hand[i].rank); // array of the other 2 tiles. use these two to move tiles accordingly
//if pair has split rules...
if (hand[i].split !== false) {
//returns true if it split..
if(this.split(pairTL, otherTL)) {
let copyArr = [pairTL[0], otherTL[0], pairTL[1], otherTL[1]];
this.setState(() => ({hand: copyArr}));
}
else {
let copyArr = otherTL.concat(pairTL);
this.setState(() => ({hand: copyArr}));
return true;
}
}
//don't split
else {
let copyArr = otherTL.concat(pairTL); //concats the two small arrays together and renders.
this.setState(() => ({hand: copyArr, pairName: pairTL[0].name, rule: 'Don't Split'}))
return true;
}
}
}
}
return false; // no pairs
}

//will not execute if there is a pair...(checkPair returns true)
checkTeenDey(hand){
//true if we have teen or dey
let teenDey = hand.find((el) => el.val === 2) !== undefined;
//if true...
if(teenDey){
let tile = hand.find((el) => el.val === 2); // teen/ dey object
let tempArr = hand.filter((el) => el.name !== tile.name); //new arr without marked teen/dey. arr.length = 3
let secondTeenDey = tempArr.find((el) => el.val === 2); //second teen/dey (not pair)
let seven = tempArr.find((el) => el.val === 7);
let eight = tempArr.find((el) => el.val === 8);
let nine = tempArr.find((el) => el.val === 9);
//if there is a second teen/dey
if (secondTeenDey){
let twoArr = tempArr.filter((el) => el.name !== secondTeenDey.name);
console.log(tile, secondTeenDey, twoArr);
return true;
}
//look for 7,8,9
else if (seven){
let without7 = tempArr.filter((el) => el.name !== seven.name);
let sevenAndTeenOrDey = [tile, seven];
let newHand = sevenAndTeenOrDey.concat(without7);
this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
return true;
}
else if(eight){
let without8 = tempArr.filter((el) => el.name !== eight.name);
let eightAndTeenOrDey = [tile, eight];
let newHand = eightAndTeenOrDey.concat(without8);
this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
return true;
}
else if(nine){
let without9 = tempArr.filter((el) => el.name !== nine.name);
let nineAndTeenOrDey = [tile, nine];
let newHand = nineAndTeenOrDey.concat(without9);
this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
return true;
}
}
// no teen or dey...
else{
return false;
}
}

//point system used for sort() in hiLowMiddle()
compare(a,b){
let comparison = 0;//no change
if(a.realValue < b.realValue){
comparison = -1;//a comes before b
}
else if(a.realValue > b.realValue){
comparison = 1;//b comes before a
}
return comparison;
}

//will not execute if there is a teen dey...
hiLowMiddle(hand){
//makes a new copy of hand and sorts it using sort()'s point system.
let sortedArr = hand.slice().sort(this.compare); //slice used, else mutates hand.
let tempHair = [sortedArr[0], sortedArr[3]];
let tempBack = [sortedArr[1], sortedArr[2]];
let hiLow = tempHair.concat(tempBack); //newly sorted arr
this.setState(() => ({hand: hiLow, rule: 'Hi-Low-Middle'}));
}

//generates new hand and updates them to state.
assignHands() {
let tempArr = [0, 0, 0, 0]; //filler array
let testArr = tilesSet.slice(); //filler array. tilesSet is untouched
//loops through and assigns random tile from deck
let newArr = tempArr.map((x) => {
let counter = Math.floor(Math.random()* (testArr.length - 1));
//used to hold the selected obj. needed since splice changes arr.length and we splice/display the different indexes.
let dummyArr = testArr[counter];
testArr.splice(counter, 1);
return dummyArr;
})
//updates state
this.setState({hand: [newArr[0], newArr[1], newArr[2], newArr[3]], show: true, history: [...this.state.history, [...newArr]]});
}

handleSubmit = (e) => {
e.preventDefault();
}

//toggle effect.
handleToggle = () => {
this.setState(() => ({cards: !this.state.cards}));
}

handleClick = () => {
this.assignHands();
//works, but not 100% properly. the changes are one step behind. fix async.
//check to see the history length. max set @ 10
if(this.state.history.length >= 10){
let temp = this.state.history.slice();
temp.shift();
this.setState(() => ({history: temp}))
}
}

//House Way
handleHW(){
if(!this.checkPair(this.state.hand)){
if(!this.checkTeenDey(this.state.hand)){
this.hiLowMiddle(this.state.hand);
}
}
}

//used for dropdown options. One per card.
userInput1(e){
this.setState({input1: e.target.value});
}
userInput2(e){
this.setState({input2: e.target.value})
}
userInput3(e){
this.setState({input3: e.target.value})
}
userInput4(e){
this.setState({input4: e.target.value})
}

//updates state and changes hands.
inputClick(){
let first = tilesSet.filter((x) => x.name === this.state.input1);
let second = tilesSet.filter((x) => x.name === this.state.input2);
let third = tilesSet.filter((x) => x.name === this.state.input3);
let fourth = tilesSet.filter((x) => x.name === this.state.input4);
let newArr = [first[0], second[0], third[0], fourth[0]];
this.setState(() => ({hand: newArr, history: [...this.state.history, [...newArr]]}));
}

render() {
return (
<div>

<Answer
show={this.state.show}
baccaratCount={this.baccaratCount}
hand={this.state.hand}
/>

<Hands
cards={this.state.cards}
hand1={this.state.hand[0].img}
hand2={this.state.hand[1].img}
hand3={this.state.hand[2].img}
hand4={this.state.hand[3].img}
/>

<Input
handleSubmit={this.handleSubmit}
userInput1={this.userInput1}
userInput2={this.userInput2}
userInput3={this.userInput3}
userInput4={this.userInput4}
inputClick={this.inputClick}
input1={this.state.input1}
input2={this.state.input2}
input3={this.state.input3}
input4={this.state.input4}
/>

<Buttons
type="button"
className="btn btn-dark"
handleClick={this.handleClick}
handleHW={this.handleHW}
hand={this.state.hand}
/>

<Features
hand={this.state.hand}
pairName={this.state.pairName}
rule={this.state.rule}
history={this.state.history}
/>

</div>
);
}
}









share|improve this question









New contributor




Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
























    up vote
    1
    down vote

    favorite












    TL;DR what should I do if I have too many methods in my parent component??



    I'm making a card game (Pai Gow Tiles) using react and I am having trouble finding a way to format my parent component. I've always heard that you should keep your components small and mine is over 300 lines. Most of it are methods that I need for my logic to set my hand 'house-way'. Think of house way as a set of rules on how to play a hand depending on what cards you're dealt. I tried separating the methods into different files, but some methods use 'this' and it throws an error.



    export default class Layout extends Component {
    constructor(props) {
    console.log("starting up");
    super(props);
    //each hand holds a randomly generated tile object from { tilesSet }
    this.state = {
    //needs empty spots for when (mounting) <Hands hand1={this.state.hand[0].img} /> else error since hand[0] doesnt exist.
    hand: ["", "", "", ""],
    cards: false,
    pairName: '',
    rule: '',
    show: false,
    history: ,
    input1: 'GJ3',
    input2: 'GJ6',
    input3: 'teen',
    input4: 'teen'
    };
    //binding in the constructor is recommended for performance.
    this.handleToggle = this.handleToggle.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.handleHW = this.handleHW.bind(this);
    this.assignHands = this.assignHands.bind(this);
    this.checkPair = this.checkPair.bind(this);
    this.checkTeenDey = this.checkTeenDey.bind(this);
    this.hiLowMiddle = this.hiLowMiddle.bind(this);
    this.compare = this.compare.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.userInput1 = this.userInput1.bind(this);
    this.userInput2 = this.userInput2.bind(this);
    this.userInput3 = this.userInput3.bind(this);
    this.userInput4 = this.userInput4.bind(this);
    this.inputClick = this.inputClick.bind(this);
    this.baccaratCount = this.baccaratCount.bind(this);
    }

    baccaratCount = (n, m) => {
    //recognizing gong , wong , or pair...
    let number = n.val + m.val;
    if(n.rank === m.rank){
    return 'Pair';
    }
    else if (n.val === 2 || m.val === 2){
    if (number === 10){
    return "Gong";
    }
    else if (number === 11){
    return 'Wong';
    }
    }
    //regular baccarat counting...
    else if (number >= 10 && number < 20){
    if (number >= 20) {
    return number -= 20;
    }
    return number -= 10;
    }
    //value is under 10, return the sum.
    return number;
    }

    //n = pairTL, n2 = otherTL
    split(n, n2){
    //Gee Joon
    if (n[0].pair === 1) {
    let combo1 = this.baccaratCount(n2[0], n[0]);
    let combo2 = this.baccaratCount(n2[1], n[1]);
    //if it meets the split requirements...
    if((combo1 >= 7 && combo2 >= 9) || (combo1 >= 9 && combo2 >= 7)){
    console.log('got em', combo1, combo2);
    return true;
    }
    else {

    return true;
    }
    }
    }

    //checks for pairs. takes an array as arg
    checkPair(hand){
    for(let i = 0; i < hand.length; i++) {
    for (let ii = 0; ii < hand.length; ii++) {
    // if there is a pair and it is not comparing to itself.
    if (hand[i].pair === hand[ii].pair && i !== ii) {
    let pairTL = hand.filter((x) => x.rank === hand[i].rank); //array of the pair tiles
    let otherTL = hand.filter((x) => x.rank !== hand[i].rank); // array of the other 2 tiles. use these two to move tiles accordingly
    //if pair has split rules...
    if (hand[i].split !== false) {
    //returns true if it split..
    if(this.split(pairTL, otherTL)) {
    let copyArr = [pairTL[0], otherTL[0], pairTL[1], otherTL[1]];
    this.setState(() => ({hand: copyArr}));
    }
    else {
    let copyArr = otherTL.concat(pairTL);
    this.setState(() => ({hand: copyArr}));
    return true;
    }
    }
    //don't split
    else {
    let copyArr = otherTL.concat(pairTL); //concats the two small arrays together and renders.
    this.setState(() => ({hand: copyArr, pairName: pairTL[0].name, rule: 'Don't Split'}))
    return true;
    }
    }
    }
    }
    return false; // no pairs
    }

    //will not execute if there is a pair...(checkPair returns true)
    checkTeenDey(hand){
    //true if we have teen or dey
    let teenDey = hand.find((el) => el.val === 2) !== undefined;
    //if true...
    if(teenDey){
    let tile = hand.find((el) => el.val === 2); // teen/ dey object
    let tempArr = hand.filter((el) => el.name !== tile.name); //new arr without marked teen/dey. arr.length = 3
    let secondTeenDey = tempArr.find((el) => el.val === 2); //second teen/dey (not pair)
    let seven = tempArr.find((el) => el.val === 7);
    let eight = tempArr.find((el) => el.val === 8);
    let nine = tempArr.find((el) => el.val === 9);
    //if there is a second teen/dey
    if (secondTeenDey){
    let twoArr = tempArr.filter((el) => el.name !== secondTeenDey.name);
    console.log(tile, secondTeenDey, twoArr);
    return true;
    }
    //look for 7,8,9
    else if (seven){
    let without7 = tempArr.filter((el) => el.name !== seven.name);
    let sevenAndTeenOrDey = [tile, seven];
    let newHand = sevenAndTeenOrDey.concat(without7);
    this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
    return true;
    }
    else if(eight){
    let without8 = tempArr.filter((el) => el.name !== eight.name);
    let eightAndTeenOrDey = [tile, eight];
    let newHand = eightAndTeenOrDey.concat(without8);
    this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
    return true;
    }
    else if(nine){
    let without9 = tempArr.filter((el) => el.name !== nine.name);
    let nineAndTeenOrDey = [tile, nine];
    let newHand = nineAndTeenOrDey.concat(without9);
    this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
    return true;
    }
    }
    // no teen or dey...
    else{
    return false;
    }
    }

    //point system used for sort() in hiLowMiddle()
    compare(a,b){
    let comparison = 0;//no change
    if(a.realValue < b.realValue){
    comparison = -1;//a comes before b
    }
    else if(a.realValue > b.realValue){
    comparison = 1;//b comes before a
    }
    return comparison;
    }

    //will not execute if there is a teen dey...
    hiLowMiddle(hand){
    //makes a new copy of hand and sorts it using sort()'s point system.
    let sortedArr = hand.slice().sort(this.compare); //slice used, else mutates hand.
    let tempHair = [sortedArr[0], sortedArr[3]];
    let tempBack = [sortedArr[1], sortedArr[2]];
    let hiLow = tempHair.concat(tempBack); //newly sorted arr
    this.setState(() => ({hand: hiLow, rule: 'Hi-Low-Middle'}));
    }

    //generates new hand and updates them to state.
    assignHands() {
    let tempArr = [0, 0, 0, 0]; //filler array
    let testArr = tilesSet.slice(); //filler array. tilesSet is untouched
    //loops through and assigns random tile from deck
    let newArr = tempArr.map((x) => {
    let counter = Math.floor(Math.random()* (testArr.length - 1));
    //used to hold the selected obj. needed since splice changes arr.length and we splice/display the different indexes.
    let dummyArr = testArr[counter];
    testArr.splice(counter, 1);
    return dummyArr;
    })
    //updates state
    this.setState({hand: [newArr[0], newArr[1], newArr[2], newArr[3]], show: true, history: [...this.state.history, [...newArr]]});
    }

    handleSubmit = (e) => {
    e.preventDefault();
    }

    //toggle effect.
    handleToggle = () => {
    this.setState(() => ({cards: !this.state.cards}));
    }

    handleClick = () => {
    this.assignHands();
    //works, but not 100% properly. the changes are one step behind. fix async.
    //check to see the history length. max set @ 10
    if(this.state.history.length >= 10){
    let temp = this.state.history.slice();
    temp.shift();
    this.setState(() => ({history: temp}))
    }
    }

    //House Way
    handleHW(){
    if(!this.checkPair(this.state.hand)){
    if(!this.checkTeenDey(this.state.hand)){
    this.hiLowMiddle(this.state.hand);
    }
    }
    }

    //used for dropdown options. One per card.
    userInput1(e){
    this.setState({input1: e.target.value});
    }
    userInput2(e){
    this.setState({input2: e.target.value})
    }
    userInput3(e){
    this.setState({input3: e.target.value})
    }
    userInput4(e){
    this.setState({input4: e.target.value})
    }

    //updates state and changes hands.
    inputClick(){
    let first = tilesSet.filter((x) => x.name === this.state.input1);
    let second = tilesSet.filter((x) => x.name === this.state.input2);
    let third = tilesSet.filter((x) => x.name === this.state.input3);
    let fourth = tilesSet.filter((x) => x.name === this.state.input4);
    let newArr = [first[0], second[0], third[0], fourth[0]];
    this.setState(() => ({hand: newArr, history: [...this.state.history, [...newArr]]}));
    }

    render() {
    return (
    <div>

    <Answer
    show={this.state.show}
    baccaratCount={this.baccaratCount}
    hand={this.state.hand}
    />

    <Hands
    cards={this.state.cards}
    hand1={this.state.hand[0].img}
    hand2={this.state.hand[1].img}
    hand3={this.state.hand[2].img}
    hand4={this.state.hand[3].img}
    />

    <Input
    handleSubmit={this.handleSubmit}
    userInput1={this.userInput1}
    userInput2={this.userInput2}
    userInput3={this.userInput3}
    userInput4={this.userInput4}
    inputClick={this.inputClick}
    input1={this.state.input1}
    input2={this.state.input2}
    input3={this.state.input3}
    input4={this.state.input4}
    />

    <Buttons
    type="button"
    className="btn btn-dark"
    handleClick={this.handleClick}
    handleHW={this.handleHW}
    hand={this.state.hand}
    />

    <Features
    hand={this.state.hand}
    pairName={this.state.pairName}
    rule={this.state.rule}
    history={this.state.history}
    />

    </div>
    );
    }
    }









    share|improve this question









    New contributor




    Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






















      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      TL;DR what should I do if I have too many methods in my parent component??



      I'm making a card game (Pai Gow Tiles) using react and I am having trouble finding a way to format my parent component. I've always heard that you should keep your components small and mine is over 300 lines. Most of it are methods that I need for my logic to set my hand 'house-way'. Think of house way as a set of rules on how to play a hand depending on what cards you're dealt. I tried separating the methods into different files, but some methods use 'this' and it throws an error.



      export default class Layout extends Component {
      constructor(props) {
      console.log("starting up");
      super(props);
      //each hand holds a randomly generated tile object from { tilesSet }
      this.state = {
      //needs empty spots for when (mounting) <Hands hand1={this.state.hand[0].img} /> else error since hand[0] doesnt exist.
      hand: ["", "", "", ""],
      cards: false,
      pairName: '',
      rule: '',
      show: false,
      history: ,
      input1: 'GJ3',
      input2: 'GJ6',
      input3: 'teen',
      input4: 'teen'
      };
      //binding in the constructor is recommended for performance.
      this.handleToggle = this.handleToggle.bind(this);
      this.handleClick = this.handleClick.bind(this);
      this.handleHW = this.handleHW.bind(this);
      this.assignHands = this.assignHands.bind(this);
      this.checkPair = this.checkPair.bind(this);
      this.checkTeenDey = this.checkTeenDey.bind(this);
      this.hiLowMiddle = this.hiLowMiddle.bind(this);
      this.compare = this.compare.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
      this.userInput1 = this.userInput1.bind(this);
      this.userInput2 = this.userInput2.bind(this);
      this.userInput3 = this.userInput3.bind(this);
      this.userInput4 = this.userInput4.bind(this);
      this.inputClick = this.inputClick.bind(this);
      this.baccaratCount = this.baccaratCount.bind(this);
      }

      baccaratCount = (n, m) => {
      //recognizing gong , wong , or pair...
      let number = n.val + m.val;
      if(n.rank === m.rank){
      return 'Pair';
      }
      else if (n.val === 2 || m.val === 2){
      if (number === 10){
      return "Gong";
      }
      else if (number === 11){
      return 'Wong';
      }
      }
      //regular baccarat counting...
      else if (number >= 10 && number < 20){
      if (number >= 20) {
      return number -= 20;
      }
      return number -= 10;
      }
      //value is under 10, return the sum.
      return number;
      }

      //n = pairTL, n2 = otherTL
      split(n, n2){
      //Gee Joon
      if (n[0].pair === 1) {
      let combo1 = this.baccaratCount(n2[0], n[0]);
      let combo2 = this.baccaratCount(n2[1], n[1]);
      //if it meets the split requirements...
      if((combo1 >= 7 && combo2 >= 9) || (combo1 >= 9 && combo2 >= 7)){
      console.log('got em', combo1, combo2);
      return true;
      }
      else {

      return true;
      }
      }
      }

      //checks for pairs. takes an array as arg
      checkPair(hand){
      for(let i = 0; i < hand.length; i++) {
      for (let ii = 0; ii < hand.length; ii++) {
      // if there is a pair and it is not comparing to itself.
      if (hand[i].pair === hand[ii].pair && i !== ii) {
      let pairTL = hand.filter((x) => x.rank === hand[i].rank); //array of the pair tiles
      let otherTL = hand.filter((x) => x.rank !== hand[i].rank); // array of the other 2 tiles. use these two to move tiles accordingly
      //if pair has split rules...
      if (hand[i].split !== false) {
      //returns true if it split..
      if(this.split(pairTL, otherTL)) {
      let copyArr = [pairTL[0], otherTL[0], pairTL[1], otherTL[1]];
      this.setState(() => ({hand: copyArr}));
      }
      else {
      let copyArr = otherTL.concat(pairTL);
      this.setState(() => ({hand: copyArr}));
      return true;
      }
      }
      //don't split
      else {
      let copyArr = otherTL.concat(pairTL); //concats the two small arrays together and renders.
      this.setState(() => ({hand: copyArr, pairName: pairTL[0].name, rule: 'Don't Split'}))
      return true;
      }
      }
      }
      }
      return false; // no pairs
      }

      //will not execute if there is a pair...(checkPair returns true)
      checkTeenDey(hand){
      //true if we have teen or dey
      let teenDey = hand.find((el) => el.val === 2) !== undefined;
      //if true...
      if(teenDey){
      let tile = hand.find((el) => el.val === 2); // teen/ dey object
      let tempArr = hand.filter((el) => el.name !== tile.name); //new arr without marked teen/dey. arr.length = 3
      let secondTeenDey = tempArr.find((el) => el.val === 2); //second teen/dey (not pair)
      let seven = tempArr.find((el) => el.val === 7);
      let eight = tempArr.find((el) => el.val === 8);
      let nine = tempArr.find((el) => el.val === 9);
      //if there is a second teen/dey
      if (secondTeenDey){
      let twoArr = tempArr.filter((el) => el.name !== secondTeenDey.name);
      console.log(tile, secondTeenDey, twoArr);
      return true;
      }
      //look for 7,8,9
      else if (seven){
      let without7 = tempArr.filter((el) => el.name !== seven.name);
      let sevenAndTeenOrDey = [tile, seven];
      let newHand = sevenAndTeenOrDey.concat(without7);
      this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
      return true;
      }
      else if(eight){
      let without8 = tempArr.filter((el) => el.name !== eight.name);
      let eightAndTeenOrDey = [tile, eight];
      let newHand = eightAndTeenOrDey.concat(without8);
      this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
      return true;
      }
      else if(nine){
      let without9 = tempArr.filter((el) => el.name !== nine.name);
      let nineAndTeenOrDey = [tile, nine];
      let newHand = nineAndTeenOrDey.concat(without9);
      this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
      return true;
      }
      }
      // no teen or dey...
      else{
      return false;
      }
      }

      //point system used for sort() in hiLowMiddle()
      compare(a,b){
      let comparison = 0;//no change
      if(a.realValue < b.realValue){
      comparison = -1;//a comes before b
      }
      else if(a.realValue > b.realValue){
      comparison = 1;//b comes before a
      }
      return comparison;
      }

      //will not execute if there is a teen dey...
      hiLowMiddle(hand){
      //makes a new copy of hand and sorts it using sort()'s point system.
      let sortedArr = hand.slice().sort(this.compare); //slice used, else mutates hand.
      let tempHair = [sortedArr[0], sortedArr[3]];
      let tempBack = [sortedArr[1], sortedArr[2]];
      let hiLow = tempHair.concat(tempBack); //newly sorted arr
      this.setState(() => ({hand: hiLow, rule: 'Hi-Low-Middle'}));
      }

      //generates new hand and updates them to state.
      assignHands() {
      let tempArr = [0, 0, 0, 0]; //filler array
      let testArr = tilesSet.slice(); //filler array. tilesSet is untouched
      //loops through and assigns random tile from deck
      let newArr = tempArr.map((x) => {
      let counter = Math.floor(Math.random()* (testArr.length - 1));
      //used to hold the selected obj. needed since splice changes arr.length and we splice/display the different indexes.
      let dummyArr = testArr[counter];
      testArr.splice(counter, 1);
      return dummyArr;
      })
      //updates state
      this.setState({hand: [newArr[0], newArr[1], newArr[2], newArr[3]], show: true, history: [...this.state.history, [...newArr]]});
      }

      handleSubmit = (e) => {
      e.preventDefault();
      }

      //toggle effect.
      handleToggle = () => {
      this.setState(() => ({cards: !this.state.cards}));
      }

      handleClick = () => {
      this.assignHands();
      //works, but not 100% properly. the changes are one step behind. fix async.
      //check to see the history length. max set @ 10
      if(this.state.history.length >= 10){
      let temp = this.state.history.slice();
      temp.shift();
      this.setState(() => ({history: temp}))
      }
      }

      //House Way
      handleHW(){
      if(!this.checkPair(this.state.hand)){
      if(!this.checkTeenDey(this.state.hand)){
      this.hiLowMiddle(this.state.hand);
      }
      }
      }

      //used for dropdown options. One per card.
      userInput1(e){
      this.setState({input1: e.target.value});
      }
      userInput2(e){
      this.setState({input2: e.target.value})
      }
      userInput3(e){
      this.setState({input3: e.target.value})
      }
      userInput4(e){
      this.setState({input4: e.target.value})
      }

      //updates state and changes hands.
      inputClick(){
      let first = tilesSet.filter((x) => x.name === this.state.input1);
      let second = tilesSet.filter((x) => x.name === this.state.input2);
      let third = tilesSet.filter((x) => x.name === this.state.input3);
      let fourth = tilesSet.filter((x) => x.name === this.state.input4);
      let newArr = [first[0], second[0], third[0], fourth[0]];
      this.setState(() => ({hand: newArr, history: [...this.state.history, [...newArr]]}));
      }

      render() {
      return (
      <div>

      <Answer
      show={this.state.show}
      baccaratCount={this.baccaratCount}
      hand={this.state.hand}
      />

      <Hands
      cards={this.state.cards}
      hand1={this.state.hand[0].img}
      hand2={this.state.hand[1].img}
      hand3={this.state.hand[2].img}
      hand4={this.state.hand[3].img}
      />

      <Input
      handleSubmit={this.handleSubmit}
      userInput1={this.userInput1}
      userInput2={this.userInput2}
      userInput3={this.userInput3}
      userInput4={this.userInput4}
      inputClick={this.inputClick}
      input1={this.state.input1}
      input2={this.state.input2}
      input3={this.state.input3}
      input4={this.state.input4}
      />

      <Buttons
      type="button"
      className="btn btn-dark"
      handleClick={this.handleClick}
      handleHW={this.handleHW}
      hand={this.state.hand}
      />

      <Features
      hand={this.state.hand}
      pairName={this.state.pairName}
      rule={this.state.rule}
      history={this.state.history}
      />

      </div>
      );
      }
      }









      share|improve this question









      New contributor




      Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      TL;DR what should I do if I have too many methods in my parent component??



      I'm making a card game (Pai Gow Tiles) using react and I am having trouble finding a way to format my parent component. I've always heard that you should keep your components small and mine is over 300 lines. Most of it are methods that I need for my logic to set my hand 'house-way'. Think of house way as a set of rules on how to play a hand depending on what cards you're dealt. I tried separating the methods into different files, but some methods use 'this' and it throws an error.



      export default class Layout extends Component {
      constructor(props) {
      console.log("starting up");
      super(props);
      //each hand holds a randomly generated tile object from { tilesSet }
      this.state = {
      //needs empty spots for when (mounting) <Hands hand1={this.state.hand[0].img} /> else error since hand[0] doesnt exist.
      hand: ["", "", "", ""],
      cards: false,
      pairName: '',
      rule: '',
      show: false,
      history: ,
      input1: 'GJ3',
      input2: 'GJ6',
      input3: 'teen',
      input4: 'teen'
      };
      //binding in the constructor is recommended for performance.
      this.handleToggle = this.handleToggle.bind(this);
      this.handleClick = this.handleClick.bind(this);
      this.handleHW = this.handleHW.bind(this);
      this.assignHands = this.assignHands.bind(this);
      this.checkPair = this.checkPair.bind(this);
      this.checkTeenDey = this.checkTeenDey.bind(this);
      this.hiLowMiddle = this.hiLowMiddle.bind(this);
      this.compare = this.compare.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
      this.userInput1 = this.userInput1.bind(this);
      this.userInput2 = this.userInput2.bind(this);
      this.userInput3 = this.userInput3.bind(this);
      this.userInput4 = this.userInput4.bind(this);
      this.inputClick = this.inputClick.bind(this);
      this.baccaratCount = this.baccaratCount.bind(this);
      }

      baccaratCount = (n, m) => {
      //recognizing gong , wong , or pair...
      let number = n.val + m.val;
      if(n.rank === m.rank){
      return 'Pair';
      }
      else if (n.val === 2 || m.val === 2){
      if (number === 10){
      return "Gong";
      }
      else if (number === 11){
      return 'Wong';
      }
      }
      //regular baccarat counting...
      else if (number >= 10 && number < 20){
      if (number >= 20) {
      return number -= 20;
      }
      return number -= 10;
      }
      //value is under 10, return the sum.
      return number;
      }

      //n = pairTL, n2 = otherTL
      split(n, n2){
      //Gee Joon
      if (n[0].pair === 1) {
      let combo1 = this.baccaratCount(n2[0], n[0]);
      let combo2 = this.baccaratCount(n2[1], n[1]);
      //if it meets the split requirements...
      if((combo1 >= 7 && combo2 >= 9) || (combo1 >= 9 && combo2 >= 7)){
      console.log('got em', combo1, combo2);
      return true;
      }
      else {

      return true;
      }
      }
      }

      //checks for pairs. takes an array as arg
      checkPair(hand){
      for(let i = 0; i < hand.length; i++) {
      for (let ii = 0; ii < hand.length; ii++) {
      // if there is a pair and it is not comparing to itself.
      if (hand[i].pair === hand[ii].pair && i !== ii) {
      let pairTL = hand.filter((x) => x.rank === hand[i].rank); //array of the pair tiles
      let otherTL = hand.filter((x) => x.rank !== hand[i].rank); // array of the other 2 tiles. use these two to move tiles accordingly
      //if pair has split rules...
      if (hand[i].split !== false) {
      //returns true if it split..
      if(this.split(pairTL, otherTL)) {
      let copyArr = [pairTL[0], otherTL[0], pairTL[1], otherTL[1]];
      this.setState(() => ({hand: copyArr}));
      }
      else {
      let copyArr = otherTL.concat(pairTL);
      this.setState(() => ({hand: copyArr}));
      return true;
      }
      }
      //don't split
      else {
      let copyArr = otherTL.concat(pairTL); //concats the two small arrays together and renders.
      this.setState(() => ({hand: copyArr, pairName: pairTL[0].name, rule: 'Don't Split'}))
      return true;
      }
      }
      }
      }
      return false; // no pairs
      }

      //will not execute if there is a pair...(checkPair returns true)
      checkTeenDey(hand){
      //true if we have teen or dey
      let teenDey = hand.find((el) => el.val === 2) !== undefined;
      //if true...
      if(teenDey){
      let tile = hand.find((el) => el.val === 2); // teen/ dey object
      let tempArr = hand.filter((el) => el.name !== tile.name); //new arr without marked teen/dey. arr.length = 3
      let secondTeenDey = tempArr.find((el) => el.val === 2); //second teen/dey (not pair)
      let seven = tempArr.find((el) => el.val === 7);
      let eight = tempArr.find((el) => el.val === 8);
      let nine = tempArr.find((el) => el.val === 9);
      //if there is a second teen/dey
      if (secondTeenDey){
      let twoArr = tempArr.filter((el) => el.name !== secondTeenDey.name);
      console.log(tile, secondTeenDey, twoArr);
      return true;
      }
      //look for 7,8,9
      else if (seven){
      let without7 = tempArr.filter((el) => el.name !== seven.name);
      let sevenAndTeenOrDey = [tile, seven];
      let newHand = sevenAndTeenOrDey.concat(without7);
      this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
      return true;
      }
      else if(eight){
      let without8 = tempArr.filter((el) => el.name !== eight.name);
      let eightAndTeenOrDey = [tile, eight];
      let newHand = eightAndTeenOrDey.concat(without8);
      this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
      return true;
      }
      else if(nine){
      let without9 = tempArr.filter((el) => el.name !== nine.name);
      let nineAndTeenOrDey = [tile, nine];
      let newHand = nineAndTeenOrDey.concat(without9);
      this.setState(() => ({hand: newHand, rule: 'Teen/Dey'}));
      return true;
      }
      }
      // no teen or dey...
      else{
      return false;
      }
      }

      //point system used for sort() in hiLowMiddle()
      compare(a,b){
      let comparison = 0;//no change
      if(a.realValue < b.realValue){
      comparison = -1;//a comes before b
      }
      else if(a.realValue > b.realValue){
      comparison = 1;//b comes before a
      }
      return comparison;
      }

      //will not execute if there is a teen dey...
      hiLowMiddle(hand){
      //makes a new copy of hand and sorts it using sort()'s point system.
      let sortedArr = hand.slice().sort(this.compare); //slice used, else mutates hand.
      let tempHair = [sortedArr[0], sortedArr[3]];
      let tempBack = [sortedArr[1], sortedArr[2]];
      let hiLow = tempHair.concat(tempBack); //newly sorted arr
      this.setState(() => ({hand: hiLow, rule: 'Hi-Low-Middle'}));
      }

      //generates new hand and updates them to state.
      assignHands() {
      let tempArr = [0, 0, 0, 0]; //filler array
      let testArr = tilesSet.slice(); //filler array. tilesSet is untouched
      //loops through and assigns random tile from deck
      let newArr = tempArr.map((x) => {
      let counter = Math.floor(Math.random()* (testArr.length - 1));
      //used to hold the selected obj. needed since splice changes arr.length and we splice/display the different indexes.
      let dummyArr = testArr[counter];
      testArr.splice(counter, 1);
      return dummyArr;
      })
      //updates state
      this.setState({hand: [newArr[0], newArr[1], newArr[2], newArr[3]], show: true, history: [...this.state.history, [...newArr]]});
      }

      handleSubmit = (e) => {
      e.preventDefault();
      }

      //toggle effect.
      handleToggle = () => {
      this.setState(() => ({cards: !this.state.cards}));
      }

      handleClick = () => {
      this.assignHands();
      //works, but not 100% properly. the changes are one step behind. fix async.
      //check to see the history length. max set @ 10
      if(this.state.history.length >= 10){
      let temp = this.state.history.slice();
      temp.shift();
      this.setState(() => ({history: temp}))
      }
      }

      //House Way
      handleHW(){
      if(!this.checkPair(this.state.hand)){
      if(!this.checkTeenDey(this.state.hand)){
      this.hiLowMiddle(this.state.hand);
      }
      }
      }

      //used for dropdown options. One per card.
      userInput1(e){
      this.setState({input1: e.target.value});
      }
      userInput2(e){
      this.setState({input2: e.target.value})
      }
      userInput3(e){
      this.setState({input3: e.target.value})
      }
      userInput4(e){
      this.setState({input4: e.target.value})
      }

      //updates state and changes hands.
      inputClick(){
      let first = tilesSet.filter((x) => x.name === this.state.input1);
      let second = tilesSet.filter((x) => x.name === this.state.input2);
      let third = tilesSet.filter((x) => x.name === this.state.input3);
      let fourth = tilesSet.filter((x) => x.name === this.state.input4);
      let newArr = [first[0], second[0], third[0], fourth[0]];
      this.setState(() => ({hand: newArr, history: [...this.state.history, [...newArr]]}));
      }

      render() {
      return (
      <div>

      <Answer
      show={this.state.show}
      baccaratCount={this.baccaratCount}
      hand={this.state.hand}
      />

      <Hands
      cards={this.state.cards}
      hand1={this.state.hand[0].img}
      hand2={this.state.hand[1].img}
      hand3={this.state.hand[2].img}
      hand4={this.state.hand[3].img}
      />

      <Input
      handleSubmit={this.handleSubmit}
      userInput1={this.userInput1}
      userInput2={this.userInput2}
      userInput3={this.userInput3}
      userInput4={this.userInput4}
      inputClick={this.inputClick}
      input1={this.state.input1}
      input2={this.state.input2}
      input3={this.state.input3}
      input4={this.state.input4}
      />

      <Buttons
      type="button"
      className="btn btn-dark"
      handleClick={this.handleClick}
      handleHW={this.handleHW}
      hand={this.state.hand}
      />

      <Features
      hand={this.state.hand}
      pairName={this.state.pairName}
      rule={this.state.rule}
      history={this.state.history}
      />

      </div>
      );
      }
      }






      playing-cards react.js jsx






      share|improve this question









      New contributor




      Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 7 hours ago









      200_success

      127k15148410




      127k15148410






      New contributor




      Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 9 hours ago









      Chris C.

      61




      61




      New contributor




      Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Chris C. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.



























          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          Chris C. is a new contributor. Be nice, and check out our Code of Conduct.










           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207696%2freact-component-for-pai-gow-game%23new-answer', 'question_page');
          }
          );

          Post as a guest





































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          Chris C. is a new contributor. Be nice, and check out our Code of Conduct.










           

          draft saved


          draft discarded


















          Chris C. is a new contributor. Be nice, and check out our Code of Conduct.













          Chris C. is a new contributor. Be nice, and check out our Code of Conduct.












          Chris C. is a new contributor. Be nice, and check out our Code of Conduct.















           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207696%2freact-component-for-pai-gow-game%23new-answer', 'question_page');
          }
          );

          Post as a guest




















































































          Popular posts from this blog

          Quarter-circle Tiles

          build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

          Mont Emei