2

I have handleClick event which by clicking renderDetail function must be run in {this.state.ShowInfo[i]} div.I do it like below code: I used callback but did not work.

class App extends React.Component {
constructor(props) {
  super(props)
  this.state = {
    data: [],
    ShowInfo: {},

  }
}
render() {
  const { data } = this.state
  const renderInfo = data.map((item, i) => {
    return (
      <div class="item">
        <div onClick={e => this.handleClick(e, item, i)}>
          <span>Click</span>
        </div>
        <div>{this.state.ShowInfo[i]}</div>
      </div>
    )
  })
  return <div>{renderInfo}</div>
}
handleClick = (e, element, i) => {
  fetch('/json.bc', {///I can see that the json.bc is loaded in network tab by result/////
    method: 'POST',
  })
    .then(response => response.text())
    .then(text => {
      let Maindata = JSON.parse(text.replace(/\'/g, '"'))
      this.setState(prevState => ({
        ShowInfo: {
          ...prevState.ShowInfo, [i]: (Maindata, i) => {
            console.log(Maindata)// console.log(Maindata) did not show anything.There is no result in this part////
            let element = Maindata
            let lenfamilies = element.families.length
            console.log(lenfamilies)//// console.log(lenfamilies) did not show anything.There is no result in this part////
            let indents = [];
            for (let j = 0; j < lenfamilies; j++) {
              let numF = i
              let numS = j
              let stingF = numF.toString()
              let stingS = numS.toString()
              index = stingF + stingS
              indents.push(
                <div>
                  <span
                    key={index}>
                  </span>
                </div>
              )
            }
            return (
              indents
            )
          }
        },
      }))
    }).catch(error => console.error(error))
  }
 }
 ReactDOM.render(<App />, document.getElementById("Result"))

<div>{this.state.ShowInfo[i]}</div> is empty by using callback.Have you any other way to call renderDetail function in handleClick event?

Edit:

class App extends React.Component {
constructor(props) {
super(props)
this.state = {
  data: [],
  ShowInfo: {},
  text: {}

 }
}
render() {
const { data } = this.state
const renderInfo = data.map((item, i) => {
  return (
    <div class="item">
      <div onClick={e => this.handleClick(e, item, i)}>
        <span>Click</span>
      </div>
      <div>{this.state.ShowInfo[i]}</div>
</div>
  )
})
return <div>{renderInfo}</div>
}

handleClick = (e, element, i) => {
  fetch('/json.bc', {
  method: 'POST',
  },)
.then(response => response.text())
.then(text => {
 let Maindata = JSON.parse(text.replace(/\'/g, '"'))
 this.setState(prevState => ({
 ShowInfo: { ...prevState.ShowInfo,[i]: this.renderDetail(Maindata, i)},
}))
}).catch(error => console.error(error))
}

renderDetail(element, i) {
 let lenfamilies = element.families.length
 let indents = []
let index = 0
for (let j = 0; j < lenfamilies; j++) {
  let numF = i
  let numS = j
  let stingF = numF.toString()
  let stingS = numS.toString()
  index = stingF + stingS
  indents.push(
  <div>
    <span
        key={index}
        onClick={e => this.handleText(e, element.families[j], index)}
      >
        Click
      </span>
      <span key={index}>
        {this.state.text[index]}
      </span>
</div>
  )
}
 return(
       indents
       )
  }
  handleText = (e, element, index) => {
        this.setState(prevState => ({
        text: { ...prevState.text, [index]: "test" }////In this part   'test' should be set in  span but it is not been set
  }))
 }
 }
5
  • Check this line [i]: (Maindata, i) => { . it should be [i]: { Commented Mar 2, 2019 at 6:34
  • Hi @Leu.Thanks for your comment. You mean I should remove ` (Maindata, i) =>` of my code? Commented Mar 2, 2019 at 6:43
  • If I remove it will have Syntax Error Commented Mar 2, 2019 at 6:43
  • yes, sure. object {} cannot have return. why don't you manipulate data before setting state this.setState(prevState => ({ ? Commented Mar 2, 2019 at 6:51
  • I am sorry, but I did not get what you mean. Can you show me in code? Commented Mar 2, 2019 at 6:55

1 Answer 1

1

Its because {this.state.ShowInfo[i]} is a function and to execute its body you need to call it by using () with function name.

Also dont forget to add a check before calling it because initial value of this.state.ShowInfo[i] will be undefined and it will throw error with ().

Write it like this [notice () with ShowInfo[i]]:

const renderInfo = data.map((item, i) => {
  return (
    <div class="item">
      <div onClick={e => this.handleClick(e, item, i)}>
        <span>Click</span>
      </div>
      {this.state.ShowInfo[i] && <div>{this.state.ShowInfo[i]()}</div>} 
    </div>
  )
})

Suggestion: Instead of storing the function in state variable, better to store data only and write a generic method that will return the jsx part for each key.

Check this snippet:

function print() {
  console.log('body of print method');
}

// it will print the function body
console.log(print);

// it will execute the function body
console.log(print());

Full Code:

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      data: [],
      showInfoData: {},
      text: {},
    }
  }

  handleClick = (e, element, i) => {
    fetch('/json.bc', {
      method: 'POST',
    })
    .then(response => response.text())
    .then(text => {
      let Maindata = JSON.parse(text.replace(/\'/g, '"'));
      this.setState(prevState => ({
        showInfoData: {
          ...prevState.showInfoData,
          [i]: Maindata,
        }
      }))
    })
    .catch(error => console.error(error))
  }

  showInfo(i) {
    let element = this.state.showInfoData[i];
    if(!element) return null;

    let lenfamilies = element.families.length
    let indents = [];
    for (let j = 0; j < lenfamilies; j++) {
      let numF = i
      let numS = j
      let stingF = numF.toString()
      let stingS = numS.toString()
      index = stingF + stingS
      indents.push(
        <div>
          <span
            key={index}
            onClick={e => this.handleText(e, element.families[j], index)}
          >
            Click
          </span>
          <span key={index}>
            {this.state.text[index]}
          </span>
        </div>
      )
    }
    return (indents);
  }

  handleText = (e, text, i) => {
    this.setState(prevState => ({
      text: { ...prevState.text, [i]: text}
    }))
  }

  render() {
    const { data } = this.state
    const renderInfo = data.map((item, i) => {
      return (
        <div class="item">
          <div onClick={e => this.handleClick(e, item, i)}>
            <span>Click</span>
          </div>
          <div>{this.showInfo(i)}</div>
        </div>
      )
    })
    return <div>{renderInfo}</div>
  }
}
Sign up to request clarification or add additional context in comments.

8 Comments

HI @Mayank Shukla. Thanks for your answer. I Changed <div>{this.state.ShowInfo[i]}</div> to {this.state.ShowInfo[i] && <div>{this.state.ShowInfo[i]()}</div>} but the result of console.log(Maindata) is undefined
I tried to call renderDetail function out side handleClick = (e, element, i) => {}) event.Every thing is done correct except onClick={e => this.handleText(e, element.families[j], index)}.By clicking onClick={e => this.handleText(e, element.families[j], index)} the text of <span key={index}>{this.state.text[index]}</span> should be test and test is going to be dynamic. I put test just as testing, but it is not been set. Could you please look at my edited code.
onClick of Click button you want to update the text or by default you want to show element.families[j] value in span?
When I click <div onClick={e => this.handleClick(e, item, i)}><span>Click</span> </div>, renderDetail(element, i) {} will be run.By now every thing is fine. But when click <span key={index} onClick={e => this.handleText(e, element.families[j], index)} > Click </span> I want the text of <span key={index}>this.state.text[index]} </span> be for example test,although the text of <span key={index}>this.state.text[index]}</span> is going to be dynamic. But For testing I put test but it is not been set.I hope you will get What I mean.
@bita added a full code section in answer, please try that code once, let me know if this is not working as you expected.
|

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.