How to disable the css changes made by Link/href - javascript

Currently there is a table with some columns which looks like this:
If one wants to see details about a company it must click on the arrow at the right-end of the row.
The problem appears when I want to make the whole row clickable, it destroys the design of the page even if there are no css classes added with that.
Here is the code when only the right-end arrow is clickable:
import React from 'react';
import { Table, Image, Icon } from 'semantic-ui-react';
import { Link } from 'react-router-dom';
export default class GenericTable extends React.PureComponent {
constructor(props) {
super(props);
}
render() {
const { headers, emptyFirstHeader, rows, entityName, idList } = this.props;
return (
<Table>
<Table.Header>
<Table.Row>
{emptyFirstHeader && <Table.HeaderCell />}
{headers.map(header => (
<Table.HeaderCell key={headers.indexOf(header)}>
{header}
</Table.HeaderCell>
))}
<Table.HeaderCell textAlign="right" />
</Table.Row>
</Table.Header>
<Table.Body>
{rows.map((row, rowIndex) => (
<Table.Row key={idList && idList[rowIndex]}>
{emptyFirstHeader && (
<Table.Cell>
<Image src={row.cells[0]} />
</Table.Cell>
)}
{
(emptyFirstHeader ? row.cells.shift() : row,
row.cells.map((cell, cellIndex) => {
if (cell === undefined) {
return null;
}
return (
<Table.Cell
key={
idList && `${idList[rowIndex]} ${headers[cellIndex]}`
}>
{cell}
</Table.Cell>
);
}))
}
<Table.Cell>
<Link
to={
entityName && `/${entityName}/${idList[rows.indexOf(row)]}`
}>
<Icon name="chevron right" />
</Link>
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
);
}
}
And when I include each <Table.Row> inside a <Link> it makes the row clickable but it breaks the design:
import React from 'react';
import { Table, Image, Icon } from 'semantic-ui-react';
import { Link } from 'react-router-dom';
export default class GenericTable extends React.PureComponent {
constructor(props) {
super(props);
}
render() {
const { headers, emptyFirstHeader, rows, entityName, idList } = this.props;
return (
<Table>
<Table.Header>
<Table.Row>
{emptyFirstHeader && <Table.HeaderCell />}
{headers.map(header => (
<Table.HeaderCell key={headers.indexOf(header)}>
{header}
</Table.HeaderCell>
))}
<Table.HeaderCell textAlign="right" />
</Table.Row>
</Table.Header>
<Table.Body>
{rows.map((row, rowIndex) => (
<Link // ADDED HERE
to={
entityName && `/${entityName}/${idList[rows.indexOf(row)]}`
}>
<Table.Row key={idList && idList[rowIndex]}>
{emptyFirstHeader && (
<Table.Cell>
<Image src={row.cells[0]} />
</Table.Cell>
)}
{
(emptyFirstHeader ? row.cells.shift() : row,
row.cells.map((cell, cellIndex) => {
if (cell === undefined) {
return null;
}
return (
<Table.Cell
key={
idList && `${idList[rowIndex]} ${headers[cellIndex]}`
}>
{cell}
</Table.Cell>
);
}))
}
<Table.Cell>
<Link
to={
entityName && `/${entityName}/${idList[rows.indexOf(row)]}`
}>
<Icon name="chevron right" />
</Link>
</Table.Cell>
</Table.Row>
</Link> // CLOSED HERE
))}
</Table.Body>
</Table>
);
}
}
How can it be done without affecting the design?

If you done need semantic HTML, you can edit the Table.Row to use Link as its components, like so. And then give the Row a class or style display: table-row
<Table.Row as={Link} style={{display: "table-row"}} to={"/"}>content of the Row</Table.Row>
You can replace the default element with the as prop and the library will pass any other props to the new component, so if you pass to it will pass the link to the Link component.

Related

React table rowProps prop doesnt log anything

[Basically, we're using this from one of our libraries. But the thing is while using it through our package the rowProps prop doesn't work]
(https://i.stack.imgur.com/fER2B.png).
import { AdvancedTable } from "ims-ui-kit";
function Table(props) {
console.log(props)
return <AdvancedTable {...props} />;
}
export default Table;
Here is another screenshot of the prop passing through the table we are using. It doesn't log anything.
[enter image description here]
<>
{alert}
<div className="content">
<ReactTable
// hasBulkActions={true}
data={data}
filterable
{...rest}
resizable={false}
columns={columns.slice()}
defaultPageSize={10}
showPaginationTop
showPaginationBottom={false}
className="-striped -highlight"
rowProps={(row) => {
onclick = () => {
console.log("hello", row);
};
}}
/>
<Modal title="Risk management">
<RiskDetail isModalOpen={isOpen} />
</Modal>
</div>
</>

Multiple buttons triggering the same modal component

I have an videos array, which in turn has objects of type Video (typing below).
I need that when clicking on the button corresponding to a specific video, I can open only one modal with the information of the clicked video.
interface VideosInfo {
id: number;
title: string;
url: string;
quiz: boolean;
}
interface PagePros {
videos: VideosInfo[]
}
Below is the component that renders the array of videos through a map, notice that inside the map, I have an onClick function that calls the modal.
import { VideoModal } from '../index';
import { useVideos } from '../../../../hooks/Videos';
export const Videos: React.FC<VideoProps> = ({ module_id }) => {
const [modalOpen, setModalOpen] = useState<boolean>(false);
const { getVideos, videos, loadingVideos } = useVideos();
const handleCloseModal = () => {
setModalOpen(false);
};
const VideosData = () => {
if (videos.length) {
return (
<List dense>
{videos?.map(video => (
<div key={video.id}>
<ListItem onClick={() => setModalOpen(true)} button>
<ListItemText primary={video.title} />
</ListItem>
<Divider />
<VideoModal
open={modalOpen}
handleClose={() => handleCloseModal()}
video={video}
video_id={video.id}
/>
</div>
))}
</List>
);
}
if (!videos.length && !loadingVideos) {
return (
<Typography variant="body1">
Não existem vídeos cadastrados neste módulo.
</Typography>
);
}
return <LoadingScreen text="Carregando vídeos..." />;
};
useEffect(() => {
getVideos(module_id);
}, [module_id, getVideos]);
return (
<Grid container spacing={2}>
<Grid item xs={12} md={12}>
<VideosData />
</Grid>
<Grid item xs={12} md={12}>
<Button variant="text" color="primary">
Novo Vídeo
</Button>
</Grid>
</Grid>
);
};
And below the VideoModal component:
export const VideoModal: React.FC<ModalProps> = ({
video,
open,
handleClose,
video_id,
}) => {
console.log('videos modal', video);
return (
<Dialog
open={open}
aria-labelledby="form-dialog-title"
onClose={handleClose}
>
<DialogTitle id="form-dialog-title">Subscribe</DialogTitle>
<DialogContent>
<h2>test</h2>
</DialogContent>
</Dialog>
);
};
I understand that the modal uses the "open" property to define whether it is open or not, but when I click the button and perform the setModalOpen, it renders a modal for each object in the array. I don't understand how I could assemble this correctly.
I solved it as follows, created a state called videoToModal of type VideosInfo and a function called handleModalOpen, passed the video parameter to the function, and in the function stored this video in the videoToModal state.
I instantiated the VideoModal component outside the map (obviously should have done this before) and passed the state to the VideoModal component's video parameter.
Below is the complete code for the component.
import React, { useEffect, useState } from 'react';
import {
Button,
Divider,
Grid,
IconButton,
List,
ListItem,
ListItemSecondaryAction,
ListItemText,
Tooltip,
Typography,
} from '#material-ui/core';
import { Delete, QuestionAnswer } from '#material-ui/icons';
import { useVideos } from '../../../../hooks/Videos';
import { useStyles } from './styles';
import { LoadingScreen } from '../../../../components/CustomizedComponents';
import { VideoModal } from '../index';
import { VideosInfo } from '../../../../hooks/Videos/types';
import { VideoProps } from './types';
export const Videos: React.FC<VideoProps> = ({ module_id }) => {
const [openModal, setOpenModal] = useState<boolean>(false);
const [videoToModal, setVideoToModal] = useState<VideosInfo>();
const classes = useStyles();
const { getVideos, videos, loadingVideos } = useVideos();
const handleCloseModal = () => {
setOpenModal(false);
};
const handleOpenModal = (video: VideosInfo) => {
setVideoToModal(video);
setOpenModal(true);
};
const VideosData = () => {
if (videos.length) {
return (
<List dense>
{videos?.map(video => (
<div key={video.id}>
<ListItem
className={classes.listItem}
onClick={() => handleOpenModal(video)}
button
>
<ListItemText
primary={video.title}
className={classes.listItemText}
/>
<ListItemSecondaryAction>
<Tooltip
placement="top"
title={
video.Quizzes?.length
? 'Clique para ver as perguntas'
: 'Clique para iniciar o cadastro de perguntas'
}
>
<IconButton edge="end" aria-label="delete">
<QuestionAnswer
color={video.Quizzes?.length ? 'primary' : 'action'}
/>
</IconButton>
</Tooltip>
<Tooltip placement="top" title="Deletar Vídeo">
<IconButton edge="end" aria-label="delete">
<Delete color="secondary" />
</IconButton>
</Tooltip>
</ListItemSecondaryAction>
</ListItem>
<Divider />
</div>
))}
<VideoModal
open={openModal}
handleClose={() => handleCloseModal()}
video={videoToModal}
/>
</List>
);
}
if (!videos.length && !loadingVideos) {
return (
<Typography variant="body1">
Não existem vídeos cadastrados neste módulo.
</Typography>
);
}
return <LoadingScreen text="Carregando vídeos..." />;
};
useEffect(() => {
getVideos(module_id);
}, [module_id, getVideos]);
return (
<Grid container spacing={2} className={classes.container}>
<Grid item xs={12} md={12}>
<VideosData />
</Grid>
<Grid item xs={12} md={12}>
<Button variant="text" color="primary">
Novo Vídeo
</Button>
</Grid>
</Grid>
);
};
Instead of using
<div key={video.id}>
can you use,
<List dense>
{videos?.map((video,i) => (
<div key={i}>
<ListItem onClick={() => setModalOpen(true)} button>
<ListItemText primary={video.title} />
</ListItem>
<Divider />
<VideoModal
open={modalOpen}
handleClose={() => handleCloseModal()}
video={video}
video_id={video.id}
/>
</div>
))}
</List>

React - Close MUI drawer from nested menu

I'm using this excellent example (Nested sidebar menu with material ui and Reactjs) to build a dynamic nested menu for my application. On top of that I'm trying to go one step further and put it into a Material UI appbar/temporary drawer. What I'd like to achieve is closing the drawer when the user clicks on one of the lowest level item (SingleLevel) however I'm having a tough time passing the toggleDrawer function down to the menu. When I handle the click at SingleLevel I consistently get a 'toggle is not a function' error.
I'm relatively new to this so I'm sure it's something easy and obvious. Many thanks for any answers/comments.
EDIT: Here's a sandbox link
https://codesandbox.io/s/temporarydrawer-material-demo-forked-v11ur
Code is as follows:
Appbar.js
export default function AppBar(props) {
const [drawerstate, setDrawerstate] = React.useState(false);
const toggleDrawer = (state, isopen) => (event) => {
if (event.type === 'keydown' && (event.key === 'Tab' || event.key === 'Shift')) {
return;
}
setDrawerstate({ ...state, left: isopen });
};
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static" color="secondary">
<Toolbar>
<IconButton
size="large"
edge="start"
color="primary"
aria-label="menu"
onClick={toggleDrawer('left', true)}
>
<MenuIcon />
</IconButton>
<img src={logo} alt="logo" />
</Toolbar>
<Drawer
anchor='left'
open={drawerstate['left']}
onClose={toggleDrawer('left', false)}
>
<Box>
<AppMenu toggleDrawer={toggleDrawer} />
</Box>
</Drawer>
</AppBar>
</Box >
)
}
Menu.js
export default function AppMenu(props) {
return MenuItemsJSON.map((item, key) => <MenuItem key={key} item={item} toggleDrawer={props.toggleDrawer} />);
}
const MenuItem = ({ item, toggleDrawer }) => {
const MenuComponent = hasChildren(item) ? MultiLevel : SingleLevel;
return <MenuComponent item={item} toggleDrawer={toggleDrawer} />;
};
const SingleLevel = ({ item, toggleDrawer }) => {
const [toggle, setToggle] = React.useState(toggleDrawer);
return (
<ListItem button onClick={() => { toggle('left', false) }}>
<ListItemIcon>{item.icon}</ListItemIcon>
<ListItemText primary={item.title} />
</ListItem>
);
};
const MultiLevel = ({ item }) => {
const { items: children } = item;
const [open, setOpen] = useState(false);
const handleClick = () => {
setOpen((prev) => !prev);
};
return (
<React.Fragment>
<ListItem button onClick={handleClick}>
<ListItemIcon>{item.icon}</ListItemIcon>
<ListItemText primary={item.title} secondary={item.description} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{children.map((child, key) => (
<MenuItem key={key} item={child} />
))}
</List>
</Collapse>
</React.Fragment>
);
};
You shouldn't call a react hook inside of any function that is not a react component. Please see React Rules of Hooks
What you could do instead is pass setToggle directly into the Drawer component as a prop and do something like this for it's onClick attribute:
onClick={() => setToggle(<value>)}

How to split a component and keep props working

I have this section of a component I want to move apart and keep its props working. The way it is below works when it is within the parent component.
<TableExpandedRow key={rowExpanded.id}>
<TableCell colSpan={headers.length + 1}>
<div>
{rowExpanded &&
rowExpanded.billingItems &&
rowExpanded.billingItems.map(
item =>
rowExpanded.id ===
item.cancellationRequestId && (
<div key={item.id}>
<p>
cancellationRequestId:{' '}
{item.cancellationRequestId}
</p>
</div>
),
)}
</div>
</TableCell>
</TableExpandedRow>
So I want to make a component like this
import React from 'react';
import PropTypes from 'prop-types';
import { DataTable } from 'carbon-components-react';
const { TableExpandedRow, TableCell } = DataTable;
const TableExpandedRowComp = ({ rowExpanded, rowExpandedId, itemId, headersLength, keyId }) => (
<TableExpandedRow key={keyId}>
<TableCell colSpan={headersLength}>
<div>
{rowExpanded &&
rowExpanded.billingItems &&
rowExpanded.billingItems.map(
item =>
rowExpanded.id === item.cancellationRequestId && (
<div key={item.id}>
<p>cancellationRequestId: {item.cancellationRequestId}</p>
</div>
),
)}
</div>
</TableCell>
</TableExpandedRow>
);
TableExpandedRow.propTypes = {
rowExpanded: PropTypes.object,
headersLength: PropTypes.array,
keyId: PropTypes.object,
};
export default TableExpandedRowComp;
And then import it at where it was before like: <TableExpandedRow {...props} />
The whole component looks like this, it is a datable:
import React from 'react';
import PropTypes from 'prop-types';
import { translate } from 'react-i18next';
import { DataTable } from 'carbon-components-react';
import TableHeaders from '../TableHeaders';
import TablePagination from '../TablePagination';
import TableToolbarComp from '../TableToolbarComp';
const {
TableContainer,
TableRow,
TableExpandHeader,
TableExpandRow,
TableExpandedRow,
Table,
TableHead,
TableHeader,
TableBody,
TableCell,
} = DataTable;
function CancellationsTable({ t, tableRows }) {
return (
<div>
<DataTable
rows={tableRows}
headers={TableHeaders(t)}
render={({ rows, headers, getHeaderProps, getRowProps }) => (
<TableContainer>
<TableToolbarComp />
<Table zebra={false} short>
<TableHead>
<TableRow>
<TableExpandHeader />
{headers.map(header => (
<TableHeader {...getHeaderProps({ header })}>
{header.header}
</TableHeader>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.map(row => (
<React.Fragment key={row.id}>
<TableExpandRow {...getRowProps({ row })}>
{row.cells.map(cell => (
<TableCell key={cell.id}>{cell.value}</TableCell>
))}
</TableExpandRow>
{row.isExpanded &&
tableRows.map(
rowExpanded =>
row.id === rowExpanded.id && (
// THIS IS THE COMPONENT I WANT TO MOVE APART
<TableExpandedRow key={rowExpanded.id}>
<TableCell colSpan={headers.length + 1}>
<div>
{rowExpanded &&
rowExpanded.billingItems &&
rowExpanded.billingItems.map(
item =>
rowExpanded.id ===
item.cancellationRequestId && (
<div key={item.id}>
<p>
cancellationRequestId:{' '}
{item.cancellationRequestId}
</p>
</div>
),
)}
</div>
</TableCell>
</TableExpandedRow>
),
)}
</React.Fragment>
))}
</TableBody>
</Table>
</TableContainer>
)}
/>
</div>
);
}
CancellationsTable.propTypes = {
t: PropTypes.func.isRequired,
tableRows: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
};
export default translate()(CancellationsTable);
Any help?
I think that you're saying that you want to consume the props, and pass the props to the child untouched?
To do this, you need to destructure in a separate statement.
<DataTable
rows={tableRows}
headers={TableHeaders(t)}
render={props => {
const { rows, headers, getHeaderProps, getRowProps } = props;
// omitted
return <TableExpandedRow {...props} />
}}

React JS Sortable Form Fields as Components

I'm trying to develop a fairly simplistic E-Mail template creator with React JS. I'm using the "react-sortable-hoc" library as a means to handle the ordering of elements on the page.
The goal is to allow users to create "Rows", rearrange rows, and within each row, have multiple "Columns" that can contain components like images, textboxes, etc...
But I keep running into the same issue with Sortable libraries. Form fields cannot maintain their own "state" when being dragged up or down. The State of a Component in React JS seems to be lost when it's in a draggable component. I've experienced similar issues with JQuery UI's Sortable but it required an equally ridiculous solution. Is it common to find that form fields are simply super difficult to rearrange?
As a "proof of concept", I am using a complex JSON object that stores all the information in the Letter.js component and passes it down as Props which are then passed down to each component. But as you can tell, this is becoming cumbersome.
Here is an example of my Letter component that handles the JSON object and sorting of Rows:
import React, {Component} from 'react';
import {render} from 'react-dom';
import {
SortableContainer,
SortableElement,
arrayMove
} from 'react-sortable-hoc';
import Row from './Row';
const SortableItem = SortableElement(({row, rowIndex, onChange, addPart}) => {
return (
<li>
<Row
row={row}
rowIndex={rowIndex}
onChange={onChange}
addPart={addPart} />
</li>
)
});
const SortableList = SortableContainer(({rows, onChange, addPart}) => {
return (
<ul id="sortableList">
{rows.map((row, index) => {
return (
<SortableItem
key={`row-${index}`}
index={index}
row={row}
rowIndex={index}
onChange={onChange}
addPart={addPart}
/> )
})}
</ul>
);
});
class Letter extends Component {
constructor(props) {
super(props);
this.state = {
rows: [],
}
this.onSortEnd = this.onSortEnd.bind(this);
this.onChange = this.onChange.bind(this);
this.addRow = this.addRow.bind(this);
this.addPart = this.addPart.bind(this);
}
addPart(event, index, value, rowIndex, columnIndex) {
console.log(value);
var part = {};
if(value === 'Text') {
part = {
type: 'Text',
value: ''
}
} else if(value === 'Image') {
part = {
type: 'Image',
value: ''
}
} else {
part = {
type: 'Empty',
}
}
const { rows } = this.state;
rows[rowIndex][columnIndex] = part;
this.setState({ rows: rows })
}
onChange(text, rowIndex, columnIndex) {
const { rows } = this.state;
const newRows = [...rows];
newRows[rowIndex][columnIndex].value = text;
this.setState({ rows: newRows });
}
addRow(columnCount) {
var rows = this.state.rows.slice();
var row = [];
for(var i = 0; i < columnCount; i++) {
var part = {
type: 'Empty',
}
row.push(part);
}
rows.push(row);
this.setState({ rows: rows })
}
onSortEnd = ({oldIndex, newIndex}) => {
this.setState({
rows: arrayMove(this.state.rows, oldIndex, newIndex),
});
};
render() {
console.log(JSON.stringify(this.state.rows));
const SideBar = (
<div className="sideBar">
<h3>Add a Row</h3>
<button className="uw-button" onClick={() => this.addRow(1)}>1 - Column</button><br/><br/>
<button className="uw-button" onClick={() => this.addRow(2)}>2 - Column</button><br/><br/>
<button className="uw-button" onClick={() => this.addRow(3)}>3 - Column</button>
<hr />
</div>
);
if(this.state.rows.length <= 0) {
return (
<div className="grid">
<p>This E-Mail is currently empty! Add some components to make a template.</p>
{SideBar}
</div>
)
}
return (
<div className="grid">
<SortableList
rows={this.state.rows}
onChange={this.onChange}
addPart={this.addPart}
lockAxis="y"
useDragHandle={true}
onSortStart={this.onSortStart}
onSortMove={this.onSortMove}
onSortEnd={this.onSortEnd}
shouldCancelStart={this.shouldCancelStart} />
{SideBar}
</div>
);
}
}
export default Letter;
And here is an example of Row:
import React, { Component } from 'react';
import { Text, Image } from './components/';
import { SortableHandle } from 'react-sortable-hoc';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import { Card, CardActions, CardHeader, CardMedia, CardTitle, CardText } from 'material-ui/Card';
import DropDownMenu from 'material-ui/DropDownMenu';
import MenuItem from 'material-ui/MenuItem';
const DragHandle = SortableHandle(() => <span className="dragHandle"></span>);
class Row extends Component {
constructor(props) {
super(props);
}
render() {
if(this.props.row !== undefined && this.props.row.length > 0) {
const row = this.props.row.map((column, columnIndex) => {
if(column.type === 'Empty') {
return (
<MuiThemeProvider key={columnIndex}>
<div className="emptyColumn">
<Card>
<DragHandle />
<CardTitle title="Empty Component"/>
<DropDownMenu value={"Empty"} onChange={(event, index, value) => this.props.addPart(event, index, value, this.props.rowIndex, columnIndex)}>
<MenuItem value={"Empty"} primaryText="Empty" />
<MenuItem value={"Text"} primaryText="Textbox" />
<MenuItem value={"Image"} primaryText="Image" />
</DropDownMenu>
</Card>
</div>
</MuiThemeProvider>
)
} else if(column.type === 'Text') {
return (
<MuiThemeProvider key={columnIndex}>
<div className="textColumn">
<Card>
<DragHandle />
<CardTitle title="Textbox"/>
<DropDownMenu value={"Text"} onChange={(event, index, value) => this.props.addPart(event, index, value, this.props.rowIndex, columnIndex)}>
<MenuItem value={"Empty"} primaryText="Empty" />
<MenuItem value={"Text"} primaryText="Textbox" />
<MenuItem value={"Image"} primaryText="Image" />
</DropDownMenu>
<Text
value={this.props.row[columnIndex].value}
onChange={this.props.onChange}
columnIndex={columnIndex}
rowIndex={this.props.rowIndex} />
</Card>
</div>
</MuiThemeProvider>
)
} else if(column.type === 'Image') {
return (
<MuiThemeProvider key={columnIndex}>
<div className="textColumn">
<Card>
<DragHandle />
<CardTitle title="Image"/>
<DropDownMenu value={"Image"} onChange={(event, index, value) => this.props.addPart(event, index, value, this.props.rowIndex, columnIndex)}>
<MenuItem value={"Empty"} primaryText="Empty" />
<MenuItem value={"Text"} primaryText="Textbox" />
<MenuItem value={"Image"} primaryText="Image" />
</DropDownMenu>
<Image
columnIndex={columnIndex}
rowIndex={this.props.rowIndex} />
</Card>
</div>
</MuiThemeProvider>
)
}
})
return (
<div className="row">
{row}
</div>
)
}
return <p>No components</p>;
}
}
export default Row;
Lastly, this is what Text.js looks like
import React, { Component } from 'react';
import ReactQuill from 'react-quill';
class Text extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ReactQuill value={this.props.value}
onChange={(text) => this.props.onChange(text, this.props.rowIndex, this.props.columnIndex)} />
)
}
}
export default Text;
So, I keep having to pass ridiculous parameters to onChange functions and other functions in order to ensure that the state is maintained while sorting and editing. So, how should I be handling this? I don't want Letter.js (which is basically App.js) to handle all of my data handling. I want each component to handle it's own. I want Text.js to handle the onChange effects of its text. But I just can't see a way around passing everything down as props.

Categories

Resources