React : Pass conditional renderings data - javascript

Assuming that this is a Toggle component to hide and display data, when called alone it's working perfectly.
Now I have a dashboard.js where I will be calling this component, but I only want to output the data, keeping the toggle switch separated in his file.
How do I pass data from the Toggle component to the Dashboard component ?
Still newbie in React and from what I learned apparently you can't pass data from child to parent.
import React, { Component } from 'react';
export default class Toggle extends React.Component{
constructor(){
super();
this.state={isShowBody: false}
}
handleClick(event) {
this.setState({isShowBody: !this.state.isShowBody})
}
render() {
return (
<div >
<div >
<span className="switch switch-sm" >
<label>
<input type="checkbox" name="select" onClick={this.handleClick.bind(this)}/>
<span />
</label>
</span>
</div>
{this.state.isShowBody ?
<div>
Data test
</div>
: null}
</div>
);
}
}

This might give you more insight in addition to what the previous answer is: Using Redux would definitely a good option but that entirely depends on the complexity of the project.
export class Toggle extends React.Component {
constructor(){
super();
this.state={
isShowBody: false
}
}
handleClick = (event) => {
this.setState({ isShowBody: !this.state.isShowBody })
}
checkbox = () => {
return (
<span className="switch switch-sm" >
<label>
<input type="checkbox" name="select" onClick={() => this.handleClick(this)}/>
</label>
</span>
)
}
dataTest = () => {
return (
<div>
Data test
</div>
)
}
render() {
return (
<div>
{this.checkbox()}
{this.state.isShowBody && this.dataTest()}
/**
* You can extract this dataSet into another component as well where you can pass initial visibility value as this.state.isShowBody
* for example
* <Dataset visibility={this.state.isShowBody} />
* */
</div>
);
}
}

If you want the parent to have information the child has you need to left up the state to the parent component and pass it to the child.
If your component has the potential to become bigger, keeping lifting up the state will become a problem so consider using a state management library like Redux.

Related

Troubles with state

I'm just started to learn react, and i have a question
Well, i can impact on state from one component to another. But can i do it in reverse?
Here's what i mean:
import React from 'react';
import Butt from './Button';
class Checkbox extends React.Component {
constructor(props) {
super();
}
render() {
return (
<div>
<Butt arg={13} />
</div>
);
}
}
export default Checkbox;
import React from 'react';
class Butt extends React.Component {
constructor(props) {
super();
this.state = {
s1: props.arg,
};
}
add = () => {
let val = this.state.s1;
val++;
this.setState({ s1: val });
};
render() {
return (
<div>
<label>
<label>
<button onClick={this.add}>add</button>
<div>{this.state.s1}</div>
</label>
</label>
</div>
);
}
}
export default Butt;
Sorry for my silly question. Thanks in advance :)
I am not sure about your question, but in react, there is a one-way flow (from parent to child) for transferring information (props, states, or ...). If you want to have access to states everywhere or set them in each direction you should use Redux or context or any other state management.
You're updating the Butt state from inside Butt so this will work fine. It won't change the value of this.props.arg though, if that's what you're asking.
Props are always non-mutable.
What you can do is have two components share the state of their parent...
class Parent extends React.Component {
state = {
val = 0
}
render () {
return (
<>
<Child1
val={this.state.val}
onChange={newVal => this.setState({ val: newVal })}
/>
<Child2
val={this.state.val}
onChange={newVal => this.setState({ val: newVal })}
/>
</>
)
}
}
Then inside the child components pass the updated value to onChange...
class Child1 extends React.Component {
handleChange() {
this.props.onChange(this.props.val + 1)
}
render() {
return (
<Button onClick={() => this.handleChange()}>
Update value
</Button>
)
}
}
This way you're just passing a new value from Child to Parent and letting Parent decide what to do with it.
Whether Child1 or Child2 sends the new value, both children will get updated when Parent calls this.setState({ val: newVal }) and changes this.state.val.

What's the right way to change the state of another component in React

I have two components, one that contains a checkbox and one that's a button. The intent is that this former component let's call it Row, if the checkbox is changed, the edit button would enable itself, and if the checkboxes are not ticked anymore the Edit button disables itself. I was planning on adding onclick event listeners but then I recently read about states and figured this is probably a better idea.
This is my Button:
class EditButton extends React.Component {
constructor() {
super();
this.state = {
clickable: false
}
}
render() {
const {clickable} = this.state
if (clickable) {
return (
<Button className="button-amber">Edit</Button>
)
} else {
return (
<Button disabled>Edit</Button>
)
}
}
}
and this is my Row component
class MyRow extends React.Component {
constructor(props) {
super(props);
this.payload = this.props.payload;
}
render() {
const toRoute = "/foo/" + this.props.payload["id"]
const tags = []
for (const [index, value] of this.props.payload["tags"].entries()) {
tags.push(<Badge>{value}</Badge>)
}
return (
<tr className="white-text">
<td>
<Form.Group>
<Form.Check type="checkbox"/>
</Form.Group>
</td>
<td>
STUFF
</td>
<td>
{this.payload["label"]}
</td>
<td>
{tags}
</td>
<td>
</td>
</tr>
);
}
}
My main app render Might look like so
render(){
<div>
<EditButton/>
<Table>
<MyRow payload=.../>
<MyRow payload=.../>
</Table>
</div>
}
And my intent is if the checkbox is clicked, check the state of all checkboxes to ensure that something is checked, if any checkbox is checked, then change the EditButton clickable state to true. What's the right way to do this? Normally I would use event listeners and individual selectors, but given that I'm using react feels like there should be a more straightforward way to modify the state of that component
There are basically two ways to share state between multiple components:
Shift state into a parent component.
Store the state externally using React Context or a state framework like Redux.
For your specific use case, I would suggest going for the first option. A good way of deciding when to use each option is to decide if the state is local to the sibling components or if it should be globally visible. Meaning that not every bit of your app state needs to be centrally managed.
Using your example, I created this snippet to show how it might work:
class Button extends React.Component {
render() {
const {onClick, disabled} = this.props
return (
<button onClick={onClick} disabled={disabled}>
Button
</button>
)
}
}
class Row extends React.Component {
render() {
const {checked, onChange} = this.props
return (
<input type="checkbox" checked={checked} onChange={onChange} />
)
}
}
class App extends React.Component {
constructor() {
super()
this.state = {
checked: false
}
this.handleCheckboxChange = this.handleCheckboxChange.bind(this)
this.handleButtonClick = this.handleButtonClick.bind(this)
}
handleCheckboxChange(e) {
this.setState({
checked: e.target.checked
})
}
handleButtonClick() {
console.log("Clicked")
}
render() {
const {checked} = this.state
return (
<div>
<Row checked={checked} onChange={this.handleCheckboxChange} />
<Button disabled={!checked} onClick={this.handleButtonClick} />
</div>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"/>
The App component handles the state of both the Row and Button components. You can handle how the child components will modify the parent state by providing callbacks that they will call upon some event, like toggling a checkbox.
React's built in state management is very limited, it's the reason a lot of users like to use Redux to handle more complex state were lots of controls interact. Personally I use my own state management using Proxys.
But you can pass setState's between components by passing them via props, below I've created a var called state that keeps track of the useStates for each component. This then allows independent setState calls between components.
I've also used React hooks here instead of class based, but the concept is the same for both..
function Button({state}) {
const butState = React.useState(false);
const [butEnabled] = butState;
state.butState = butState;
return <button
disabled={!butEnabled}
>Button</button>;
}
function Row({state, row}) {
const rowState = React.useState(false);
const [checked, setChecked] = rowState;
state.rows[row] = rowState;
function toggleChecked() {
state.rows[row][0] = !checked;
state.butState[1](state.rows.some(b => b[0]));
setChecked(state.rows[row][0]);
}
return <div>
<input value={checked} type="checkbox" onChange={toggleChecked}/>
</div>
}
function Page() {
const state = {
rows: []
}
return <div>
<Button state={state}/>
<Row state={state} row={1}/>
<Row state={state} row={2}/>
</div>
}
ReactDOM.render(
<Page/>,
document.querySelector('#mount'));
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="mount"/>

Accessing the data from one component to another component

Hi I am starting to learn reactjs. So after understanding the basics Im starting to work on database connectivity using reactjs. In the code Im trying to get the userId and Password to establish a DB connectivity and trying to list the tables available in the DB. In the Login.js I have create a form (userId and Password) when login button is clicked I will make a connectivity and execute the Show Table query to list all the tables in the DB, and move to the Table.js page where I try to list the available tables. Right now I able to connect to the DB but not able to display the tables in the Table.js, so how to display the tables list in the Table.js file, because I have placed my DB connectivity and query inside a button event in the Login.js. Also Is there a possible to declare a variable global and access it across the another js files. Any help would be great, thank you.
Login.js
import React from 'react';
import TableContent from './tables';
class Login extends React.Component{
constructor(){
super();
this.state={
showComponent : false,
};
// this.buttonClick = this.buttonClick.bind(this);
}
buttonClick(event){
event.preventDefault();
this.setState({
showComponent: true,
})
var db = require('#dataBase/dynamoConnect')({
"UserId": "XXXXXXXXXXXXXXXXXXXXXXXX",
"Password": "YYYYYYYYYYYYYYY",
"region": "ZZZZZZZZZZ"
});
db.query("SHOW TABLES",(err,data)=>{
const tableList = data;
console.log(tableList);
})
}
render(){
return(
<div>
<form>
<label>User Id :</label>
<input type="text" className="test"/>
<br/>
<label>Password :</label>
<input type="text" className="test" />
<button onClick={this.buttonClick.bind(this)} className="connect" > Login</button>
</form>
{this.state.showComponent && <TableContent />}
</div>
)
}
}
export default Login;
Table.js
import React from 'react';
class TableContent extends React.Component {
constructor() {
super();
this.state = {
showComponent: false,
};
this.buttonClick = this.buttonClick.bind(this);
}
buttonClick(event) {
event.preventDefault();
this.setState({
showComponent: true,
})
}
render() {
return (
<div>
<form>
<div id="first">
<label> Table </label>
<br />
//Display the tables from DB here
<select name="sometext" multiple="multiple" >
<option>Table1</option>
<option>Table2</option>
<option>Table3</option>
<option>Table4</option>
<option>Table5</option>
</select>
</div>
<div id="second">
<label> SQL </label>
<br/>
<textarea rows="4" cols="50">SQL </textarea>
</div>
<button onClick={this.buttonClick.bind(this)} > Execute </button>
<div id="third" >
{this.state.showComponent && <SampleTable />}
</div>
</form>
</div>
)
}
}
export default TableContent;
First.
The Table.js component need to know the data to display.
1 - you have to save result of the query in component state, by calling this.setState({tableData: tableList}) in query callback:
db.query("SHOW TABLES",(err,data)=>{
const tableList = data;
this.setState({
tableData: tableList,
});
})
2 - you need to pass saved result as a property to TableContent, like this:
in Login.js:
{this.state.showComponent && <TableContent data={this.state.tableData} />};
3 - render data in the child component. You can get access to it via this.props.data. You can iterate over an result array and render all table rows in single loop. Take a look at this react doc.
Second:
Also Is there a possible to declare a variable global and access it across the another js files
In short - yes. You can export functions, variables, classess from your module.
Small example:
// scriptA.js;
export const a = 42;
// scriptB.js;
import { a } from 'path/to/scriptA.js';
console.log(a) // will print 42;
This example assumes you are using es6 import/export feature. You can require it as well.
There are a number of strategies for communicating between components, but the easiest way (without using Flux or Redux) is to use a parent component to act as a mediator for the communication.
Basically, the parent passes a callback to one component that sets some state to pass down the the other component, for example:
Child creating data
class Child1 extends React.Component {
constructor() {
super()
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.props.setMessage("hello world")
}
render() {
return <button onClick={this.handleClick}>say hello</button>
}
}
Child using data
const Child2 = ({message}) => {
return <p>{message}</p>
}
Parent
class Parent extends React.Component {
constructor() {
super()
this.state = { message: "" }
}
render() {
return (
<div>
<Child1 setMessage={(message) => this.setState({ message })} />
<Child2 message={this.state.message} />
</div>
)
}
}
If they can't be siblings, this pattern can get a bit strenuous, but can still be achieved by having the mediator component as the lowest common ancestor and passing the relevant props all the way down. At that point though, you may want to investigate Flux or Redux and externalising the state from the components entirely.

Passing props/state to/from parent component

So I have a parent component and a log in component.
I want the user to enter their details and then hit submit and then store/pass those details around so they can be used by other components.
how is this best done in React?
for example I have this input field inside my log in component
<p>
<input type="text" id="playerName" value={this.props.nameValue} onChange={this.props.handleNameChange}/>
</p>
Then I want to pass the value that is entered to the parent component
I have this function in my parent component:
handleNameChange(event){
this.setState({nameValue: event.target.value})
};
and in my return I have:
return (
<div>
<LoginPage handleClick={this.handleClick.bind(this)} handleNameChange={this.handleNameChange.bind(this)}/>
</div>
)
However, when I console.log(nameValue) I get undefined. any ideas? can add more code if necessary/relevant
From your example you never pass nameValue to the child component.
Updated your example of rendering the LoginPage, passing this.state.nameValue into the child component via props:
return (
<div>
<LoginPage
handleClick={this.handleClick.bind(this)}
handleNameChange={this.handleNameChange.bind(this)}
nameValue={this.state.nameValue}
/>
</div>
)
Your approach using state and props is fine. Are you sure that you shouldn't just be using...
console.log(this.state.nameValue);
This is a working example
class Parent extends React.Component {
constructor() {
super();
this.state = {
nameValue:''
};
}
render() {
return (
<Child handleClick={this.handleClick.bind(this)} handleNameChange={this.handleNameChange.bind(this)} nameValue={this.state.nameValue} />
);
}
handleNameChange(e) {
this.setState({
nameValue: e.target.value
});
}
handleClick() {
alert(this.state.nameValue);
}
}
class Child extends React.Component {
render() {
return (
<div>
<input type="text" value={this.props.nameValue} onChange={this.props.handleNameChange} />
<button onClick={this.props.handleClick}>Click Me!</button>
</div>
);
}
}
JSFiddle here.

onclick show and hide data in react.js

i have component which is showing data in the webpage
I want to write another component and create buutton in it. which just hide other component on clicking the button and show basic input field form.
My code is something like this
component app
class App extends React.Component{
constructor(props) {
super(props);
this.state= {
filter: null,
};
this.setFilter = this.setFilter.bind(this);
}
setFilter(filter) {
this.setState({filter: filter})
}
render(){
let filteredPassword = details_data.filter(
(detail) =>{
console.log(detail.website.toLowerCase(), this.state.filter)
return detail.website.toLowerCase().indexOf(this.state.filter)!= -1;
}
);
return (
<ul>
<Filter onUpdateFilter={this.setFilter} />
{
filteredPassword.map((detail)=>{
return <Detail item={detail}
key={detail.id}/>
})
}
</ul>
)
}
}
Another Detail component
class Filter extends React.Component{
constructor() {
super();
this.state={
search: 'Search'
}
}
updateSearch(event) {
this.props.onUpdateFilter(event.target.value.substr(0,40))
}
formShow(){
}
render() {
return (
<div>
<input id="search" type="text" placeholder={this.state.search} onChange={this.updateSearch.bind(this)}/>
<input id="button1" type="button" value="+" onClick={this.formShow()}/>
</div>
)
}
}
Few other component like this.
i am trying to hide the table and form button above is used to "show form" button.
class Form extends React.Component {
render() {
return(
<div>
<form>
<input type="text" placeholder="username" />
<input type="password" placeholder="username" />
</form>
</div>
)
}
}
Guide me how to do this.. thank you
Without looking too much to your code (it's a bit messy) it seems to me what you want to achieve is to communicate two components. Component A will react to a button click event and tell: 1) component B to hide and 2) component C to show up.
The way of doing this depends on if the components have hierarchical relationship or not. I would recommend start by reading this chapter of the official React documentation. Then, here is also a great article on component communication strategies in React.
On top of that, some patterns that focus specifically on this have achieved great success, like Flux or Redux.
Hope it helps.

Categories

Resources