0

When a radio button is clicked (the set of buttons coded in Test.js) a function called handleclick is performed. In this I update the array, however I fail to resend it to the graph_test.js. So graph_test.js receives the initial array being filled with 0's but it never receives the updated versions.
What I want is a array of 0 and 1's, each index representing a region. When a button is clicked the 0/1 turns into the opposite value.
I need this dynamically updating as in graph_test.s, I am going to code lines on a graph based on which indexes in the array have 1's beside it. Test.js - where i fill,create,update the array

// When radio buttons checked, change corresponding value in array if 0 change to 1 and if 1 change to 0
// This will be used in the graph component, and will enable the functionality of selcting one region or multiple region.
// As the graph will be plotted based on which regions are noted 1 in the array 


import $ from "jquery";
import Graph_Test from "./Graph_Test.js";
import React, { useState } from "react";
const Test = props => {
  const total_regions = (JSON.parse(JSON.stringify(props.test)).length); // gets the number of regions
  const [array, setArray] = useState(Array(total_regions.length).fill(0));
    //when a radio button is clicked change its corresponding in the array

//when a radio button is clicked change its corresponding in the array
const handleClick = (item, idx) => {
  if (array[idx] == 1) {
    array[idx] = 0;
  } else {
    array[idx] = 1;
  }
  setArray(array);
};


  return (
    // displays radio buttons depending on the number of objects in json
    <div>
    <div>
   <Graph_Test array={array} testing={[]} />
    </div>
    <div>
    {props.test.map((item, idx) => { 
      return (
        <label key={idx}>
          <input className="region" type="radio" value={idx} onClick={() => handleClick(item, idx)}/>
          <span>{idx}</span> 
        </label>
      );
    })}  
    </div>

    </div>
  );
};
export default Test;

Graph_test where the array is called:

import React from 'react';
import $ from "jquery";
//<h1>{props.testing.map}</h1>
const Graph_Test = props => { 
  console.log(`ARRRAy ${props.array.length}`);
    return(
      <div>
        <div>
        {props.array && props.array.length > 0 && <p>{props.array[0]}</p> }
        </div>     
        <div>
        {props.testing && props.testing.map((item, idx) => { 
          return (
            <label key={idx}>
              <input className="region" type="radio" value={idx} />
              <span>{idx}</span> 
            </label>
          );
        })}  
        </div>
      </div >
    );
  };export default Graph_Test;

app.js:

import "bootstrap/dist/css/bootstrap.css";
import React from "react";
import ReactPlayer from 'react-player'
import LeftPane from "./components/LeftPane.js";
import Video from "./components/Video.js";
//import Footer from "./components/Footer.js";
import Test from "./components/Test.js";
import Graph_Test from "./components/Graph_Test.js";
//import './App.css';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { apiResponse: [] };

  }
  // Comunicate with API
  callAPI() {
    fetch("http://localhost:9000/IntensityAPI") //React app talks to API at this url
      .then(res => res.json())
      .then(res => this.setState({ apiResponse: res }));
  }
  componentWillMount() {
    this.callAPI();
  }

  render() {
    return (
      <div className="App">
          <div class="row fixed-top fixed-bottom no-gutters"  >
            <div class="col-3 fixed-top fixed-bottom">
              <LeftPane></LeftPane>
            </div>
            <div class="offset-md-3 fixed-top fixed-bottom" >
              <Video></Video>
            </div>
            <div class=" col-3 fixed-bottom">
            <Test test = {this.state.apiResponse}/>
            <Graph_Test testing = {this.state.apiResponse} array={[]}  />

            </div>      
            </div>

      </div>
    );
  }
}
export default App;
//  <Footer test = {this.state.apiResponse}/>

I've generated a sand box. You can see the 0, so when a radio button is pressed i want it to turn to 0 and then when it is pressed again i want it to turn back to 1. Is this done with states? Also ignore the first row of radio buttons just have it there for testing purposes its the next row that it should work it https://codesandbox.io/s/arraypropproblem-8ec6d?file=/src/components/Test.js

Sue
  • 225
  • 3
  • 9

1 Answers1

1

Your codesandbox returns a fetch error, but yes you are right: through implementing a general state, used between your two components,the handleClick update will also be correctly reflected in graph_test

If they are siblings, elevate the state to the parent component and it should do. Example:

class Example extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isClicked: false
    };
  }

  handleClick = () => {
    this.setState({ ...this.state, isClicked: !this.state.isClicked });
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click</button>
      </div>
    );
  }
}

export default Example;

and passing this state to any other child component you want to use it in

Slim
  • 663
  • 3
  • 11
  • Thank you @Slimcody, I’ve messed around with it but struggling with the states could you show me a example – Sue Apr 11 '20 at 16:40
  • Added a simple example. Also a similar question with more detailed code https://stackoverflow.com/questions/36143767/react-js-communicating-between-sibling-components – Slim Apr 11 '20 at 17:08
  • do i need to include the constructor in the sibling component also. And can i use constructor with the way my components are as they do not have render? – Sue Apr 11 '20 at 17:13
  • 1
    no you don't need the constructor in the siblings, and they can also be simply stateless functional components (but don't forget to pass them props as an input) – Slim Apr 11 '20 at 17:14
  • I tried to use states however it still doesnt work, can you see a problem with that ive updated it – Sue Apr 11 '20 at 17:21
  • 1
    I made you this simplified sandbox where you can see it working, you can update it to suit your need https://codesandbox.io/s/small-architecture-tvxmg?file=/src/App.js – Slim Apr 11 '20 at 17:47
  • Thank you ! when you say ... is that to be filled in or will it work in my case – Sue Apr 11 '20 at 17:51
  • 1
    No it works as is, it is called a spread operator, which basically makes a copy of an element and adds the new item at the end. For the simplified sandbox it wouldn't be needed, but if you stored more info in your state then it should be used to not overwrite the rest – Slim Apr 11 '20 at 17:53
  • im having difficultly trying to adapt it to my problem, will handleclick be in app.js and will it contain changing the same as clickhandle in test.js – Sue Apr 11 '20 at 18:05
  • And because i am sending in other prop also to the children will that work? – Sue Apr 11 '20 at 18:14