I just started to learn to react 2 days ago and I’m having a hard time with react’s setstate
method, all I know is use revstate
parameter if want to change state based on previous state, and callback parameter to be executed right after the state change (please correct me if this wrong), so I just change the array content (which I render it using javascript’s array.map
) and I wish it renders right after the state is changed, it is changing but delayed, it only render after I do another click but the render method is called
for any senpai out there thanks for the help.
Handle click for changing to render content based on index passed on my button “onClick”
class App extends React.Component { constructor(props){ super(props) this.state = { clickeditem : -1 } this.torender = [ { display : "first", content : [] }, { display : "second", content : [] } ] } handleclick = (i) =>{ this.setState(prevstate=>{ if (prevstate.clickeditem === -1) { return {clickeditem : i} } else { return prevstate.clickeditem === i ? {clickeditem : -1} : {clickeditem : i} } },() => { return this.state.clickeditem === -1 ? (this.torender[0].content = [], this.torender[1].content = []) : (this.state.clickeditem === 0) ? (this.torender[0].content = ["torender-0 content","torender-0 content"],this.torender[1].content = []) : (this.state.clickeditem === 1) ? (this.torender[1].content = ["torender-1 content","torender-1 content"],this.torender[0].content = []) : null }) } render(){ return( <div> <ul> { this.torender.map((item,index) => { return( <li key = {index}> {item.display} <ul> {item.content.map((content,contentindex) => { return(<li key = {contentindex}>{content}</li>) })} </ul> </li> ) }) } </ul> <button onClick={()=>this.handleclick(0)}>first-button</button> <button onClick={()=>this.handleclick(1)}>second-button</button> </div> ) } } ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="root"></div>
Advertisement
Answer
Refactor your code and Approach the simpler way
Actually, you shouldn’t use the second param callback
.
Whenever the state is changed, the life cycle of React Js will re-render it properly (See the image below to clarify in detail ^^!)
There are some things to note:
Move the content of each item in
torender
accordingly –> This is clearer about the initial data as well as it should not be mutated.Default
clickeditem
is one of the items intorender
, for example, the first item.After that, you just control the content to be rendered in this way
___________ The condition to call renderContent() method ______________ {index === this.state.clickeditem && this.renderContent(item)} _____________renderContent() looks like below_____________ renderContent = (item) => { return ( <ul> {item.content.map((content, contentindex) => { return <li key={contentindex}>{content}</li>; })} </ul> ); };
class App extends React.Component { constructor(props) { super(props); this.state = { clickeditem: 0 }; this.torender = [ { display: "first", content: ["torender-0 content", "torender-0 content"] }, { display: "second", content: ["torender-1 content", "torender-1 content"] } ]; } handleclick = (index) => { this.setState({clickeditem: index}); }; renderContent = (item) => { return ( <ul> {item.content.map((content, contentindex) => { return <li key={contentindex}>{content}</li>; })} </ul> ); }; render() { return ( <div> <ul> {this.torender.map((item, index) => { return ( <li key={index}> {item.display} {index === this.state.clickeditem && this.renderContent(item)} </li> ); })} </ul> <button onClick={() => this.handleclick(0)}>first-button</button> <button onClick={() => this.handleclick(1)}>second-button</button> </div> ); } } ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="root"> </div>