Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

import React, { useState } from 'react';
import './StockQuotes.css'; 
import { createMuiTheme, withStyles, makeStyles, ThemeProvider } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';
import stockData from '../util/stockData';
import { useDispatch } from 'react-redux';
import { getStocksOwned } from '../slices/stocksOwnedSlice';

const StockQuotes = () => {

    const [sharesToBuy, setSharesToBuy] = useState(stockData);
    const dispatch = useDispatch();
    
    const handleChange = (event, index) => {
        stockData[index].owned = parseInt(event.target.value);
        setSharesToBuy(stockData);
    }
    
    const handleClick = (event, index) => {
        event.preventDefault();
        dispatch(getStocksOwned(sharesToBuy));
        stockData[index].owned = 0;
    }

    const StyledTableCell = withStyles((theme) => ({
        head: {
            backgroundColor: theme.palette.common.black,
            color: theme.palette.common.white,
        },
        body: {
            fontSize: 14,
        },
    }))(TableCell);

    const StyledTableRow = withStyles((theme) => ({
        root: {
            '&:nth-of-type(odd)': {
            backgroundColor: theme.palette.action.hover,
            },
        },
    }))(TableRow);

    const useStyles = makeStyles((theme) => ({
        margin: {
            margin: theme.spacing(1),
        },
        table: {
            minWidth: 700,
            },
    }));

    const classes = useStyles();

    const theme = createMuiTheme({
            palette: {
                primary: {main: '#00e676'},
            },
        });

    return(
        <TableContainer component={Paper}>
            <Table className={classes.table} aria-label="customized table">
                <TableHead>
                    <TableRow>
                        <StyledTableCell>Stock Name</StyledTableCell>
                        <StyledTableCell align="right">Current Price</StyledTableCell>
                        <StyledTableCell align="right">Shares</StyledTableCell>
                        <StyledTableCell align="right">Order</StyledTableCell>
                    </TableRow>
                </TableHead>
                <TableBody>
                {stockData.map((stock, index) => (
                    <StyledTableRow key = {index} >
                        <StyledTableCell component="th" scope="row">
                            {stock.name}
                        </StyledTableCell>
                        <StyledTableCell align="right">${stock.price}</StyledTableCell>
                        <StyledTableCell align="right"><input type="number" onChange={event => handleChange(event, index)}></input></StyledTableCell>
                        <StyledTableCell align="right">
                            <ThemeProvider theme={theme}>
                                <Button variant="contained" color="primary" className={classes.margin} onClick={event => handleClick(event, index)}>
                                    BUY
                                </Button>
                            </ThemeProvider>
                        </StyledTableCell>
                    </StyledTableRow>
                    ))}
                </TableBody>
            </Table>
        </TableContainer>
    )
}

export default StockQuotes;

I'm trying to get stockData[index].owned to 0 after I click submit button. Usually straight forward, but this time 8 input fields are created through mapping stockData json file which contains 8 objects. So if I put value property by input tag then type, entire 8 input field changes. So I coded this way except after I click, I get "TypeError: Cannot assign to read only property 'owned' of object '#'". What can I do?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
205 views
Welcome To Ask or Share your Answers For Others

1 Answer

A few things going on here:

  1. stockData appears to just be an initial value for setting the component state. Once state is initialized, update and read from sharesToBuy so those changes flow to your component tree.
  2. Don't mutate objects/state. That can cause bugs and prevent your component from updating properly. Instead, create a new copy with updated values.
  3. Make your input controlled and update the value based on state changes.
// Convenience function for updating state.
const updateOwnedValue = (index, owned) => {
  // Instead of mutating the array/object, create a copy with the updated values
  // and then update state so the changes flow down to your components.
  const newState = sharesToBuy.map((stock, idx) => (
    idx === index ? { ...stock, owned } : stock
  ));

  setSharesToBuy(newState);
};

const handleChange = (event, index) => {
  updateOwnedValue(index, parseInt(event.target.value));
}

const handleClick = (event, index) => {
  event.preventDefault();
  dispatch(getStocksOwned(sharesToBuy));
  updateOwnedValue(index, 0);
}

...
// Iterate over component state instead of the imported value.
{sharesToBuy.map((stock, index) => (
  ...
  <input
    type="number"
    onChange={event => handleChange(event, index)}
    value={
      // This makes your input a controlled component.
      // The value will respond to state changes.
      stock.owned
    }
  />
  ...
))}


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...