简体   繁体   English

如何在 React 函数之间共享状态并在更改时重新渲染

[英]How to share state between React function and re-render on changes

I have a react component that renders a forms with checkboxes and a chart (Victory).我有一个反应组件,它呈现带有复选框和图表(胜利)的表单。 I want the component to show the active checkboxes in the graph (each checkboxes has its api url, for simplicity, the code below shows useless data and no fetching).我希望组件在图中显示活动复选框(每个复选框都有其 api url,为简单起见,下面的代码显示无用的数据并且没有获取)。 There are multiple problems in this code:这段代码存在多个问题:

1) The activestock state always seem to be one step behind in the point of view of the console.log, in the console it show the previous state instead of the actual content of the array. 1)从console.log的角度来看,activestock状态似乎总是落后一步,在控制台中它显示的是之前的状态而不是数组的实际内容。 But in the React Dev Tools it shows the activestock correctly.但是在 React Dev Tools 中,它正确地显示了活性库存。

2) The VictoryChart doesnt get re-rendered even though its props (which is the activestock) changes, even though I can see in the React Dev Tools that multiple VictoryLines components exist. 2) 即使 VictoryChart 的 props(即活动库存)发生变化,VictoryChart 也不会重新渲染,即使我可以在 React Dev Tools 中看到存在多个 VictoryLines 组件。 It's like the parents doesn't rerender on state changes, but I thought that by passing a state in props, you shared state between components?就像父母不会重新渲染状态更改,但我认为通过在道具中传递状态,您可以在组件之间共享状态?

3) Because the hooks rerenders the components, the checkboxes doesn't show a check when clicked. 3) 因为钩子会重新渲染组件,所以单击复选框时不会显示选中状态。

Here is a sandbox link: https://codesandbox.io/s/crazy-murdock-3re1x?fontsize=14&hidenavigation=1&theme=dark这是一个沙箱链接: https : //codesandbox.io/s/crazy-murdock-3re1x?fontsize=14&hidenavigation=1&theme=dark

import React, {useState, useEffect}from 'react'
import Card from 'react-bootstrap/Card';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import { VictoryLine, VictoryChart } from 'victory';



export default function HomeCards(props){

    const [activestock, setActiveStock] = useState([])

    function handleActiveStocks(props){

        if (activestock.includes(props) === false){
             setActiveStock([...activestock, props])
             console.log(activestock)

        } 
        else {
            setActiveStock(activestock.filter(activestock => activestock !== props))           
            console.log(activestock)
        }
    }


    function Lines(props){
        const charts = []

        if (props.chart !== undefined){
            props.chart.map(function(val, index){
                charts.push(

                    <VictoryLine data={[
                        {x:index+1, y:index+2},
                        {x:index+2, y:index+4}
                    ]}/>

                )
            })
            return charts
    }  
        return null
    }

    function RealCharts(props){

        return(
        <VictoryChart>
            <Lines chart={props.stocks}></Lines>
        </VictoryChart>
        )
    }

    function Forms(props){

        const hg=[]
        props.text.map(function(val, index){

            hg.push(
                <form>
                    {val} <input type='checkbox' onClick={()=> handleActiveStocks(val)}/> {index}
                </form>
            )
        })
        return(hg)
    }

    return(
        <Container fluid>
           <Row style={{position:'relative', top:'2vh'}}>

                <Card style={{width:props.width}}>
                    <Card.Header>U.S Equity</Card.Header>
                    <Forms 
                    text={['S&P 500', 'NASDAQ',' DOW', 'Russel 1000', 'Large Cap', 'Small Cap', 'MSFT', 'FB']}
                         />
                </Card>

                <Card>
                    {/* <VictoryChart >
                        <Lines chart={activestock}/>
                    </VictoryChart> */}
                    <RealCharts stocks={activestock}/>
                </Card>


            </Row>
        </Container>
    )
}

You need a checked={some_value_here} for checkbox to be checked.您需要一个checked={some_value_here}来检查复选框。

import React, { useState, useEffect } from "react";
import Card from "react-bootstrap/Card";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import { VictoryLine, VictoryChart } from "victory";

export default function HomeCards(props) {
  const [activestock, setActiveStock] = useState([]);

  function handleActiveStocks(props) {
    if (activestock.includes(props) === false) {
      setActiveStock([...activestock, props]);
      console.log(activestock);
    } else {
      setActiveStock(activestock.filter(activestock => activestock !== props));
      console.log(activestock);
    }
  }

  function Lines(props) {
    const charts = [];

    if (props.chart !== undefined) {
      props.chart.map(function(val, index) {
        charts.push(
          <VictoryLine
            data={[
              { x: index + 1, y: index + 2 },
              { x: index + 2, y: index + 4 }
            ]}
          />
        );
      });
      return charts;
    }
    return null;
  }

  function RealCharts(props) {
    return (
      <VictoryChart>
        <Lines chart={props.stocks} />
      </VictoryChart>
    );
  }

  // useEffect()

  function Forms(props) {
    const hg = [];
    props.text.map(function(val, index) {
      console.log(activestock)
      // check the value exists in the activeStock
      const checked=activestock.includes(val);
      hg.push(
        <form>
          {val}{" "}
          <input type="checkbox" checked={checked} onClick={() => handleActiveStocks(val)} />{" "}
          {index}
        </form>
      );
    });
    return hg;
  }

  return (
    <Container fluid>
      <Row style={{ position: "relative", top: "2vh" }}>
        <Card style={{ width: props.width }}>
          <Card.Header>U.S Equity</Card.Header>
          <Forms
            text={[
              "S&P 500",
              "NASDAQ",
              " DOW",
              "Russel 1000",
              "Large Cap",
              "Small Cap",
              "MSFT",
              "FB"
            ]}
          />
        </Card>

        <Card>
          {/* <VictoryChart >
                        <Lines chart={activestock}/>
                    </VictoryChart> */}
          <RealCharts stocks={activestock} />
        </Card>
      </Row>
    </Container>
  );
}

The shared state is not wrong, you just need to add necessary check before return it.共享状态没有错,您只需要在返回之前添加必要的检查即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM