Предотвратить повторную визуализацию массива объектов - PullRequest
0 голосов
/ 24 марта 2020

У меня есть компонент Ul, который содержит массив объектов с разными значениями. Каждый элемент с именем TestCase в этом списке имеет кнопку, которая выполняет повторный вызов и обновляет свой объект. Однако не все TestItems должны быть обновлены. только те, чья кнопка нажата. Состояние этого массива хранится в родительском компоненте Continer, называемом TestCaseContainer. Однако моя кнопка обновит состояние в соответствии с введенным TestItem в массиве. это заставляет весь список перерисовываться. Как я могу отображать только измененные TestItems вместо того, чтобы отображать весь ul при каждом обновлении элемента. Я читал об использовании useMemo, чтобы компонент мог запоминать переданные реквизиты, однако я не знаю, как правильно это реализовать.

Как я могу остановить все повторные рендеринга !! Заранее извиняюсь за грязный код!

Вот мой код

Регрессия. js - Содержит все состояния

const Testing = forwardRef((props,ref) => {


  const templateTestItem = {id:0,formData:{date:'',env:'',assetClass:'',metric:'',nodeLevel:'',nodeName:'',testName:'',dataType:'',tradeId:''},results:[],isLoading:false}
  const testCaseRef = useRef()
  const [isRun, setIsRun] = useState(false)
  const [testItems, setTestItems] = useState([ templateTestItem])
  const [stats,setStats] = useState(null)


  const addTestItem = () => {

    const newIndex = testItems.length 
    // console.log(newIndex)

    const templateTestItem = {id:newIndex,formData:{date:'',env:'',assetClass:'',metric:'',nodeLevel:'',nodeName:'',testName:'',dataType:'',tradeId:''},results:[],isLoading:false}
    setTestItems([...testItems, templateTestItem])

  }

  const addUploadCases = (cases) => {

    setTestItems([])
    const UploadedItems = cases.map((item,index)=>{

        return{
          id:index,
          formData:{
            date:item['date'],
            env:item['env'],
            assetClass:item['asset_class'],
            metric:item['metric'],
            nodeLevel:item['node_level'],
            nodeName:item['node_name'],
            testName:item['test_name'],
            dataType:item['dataType'],
            tradeId:item['tradeId']
          },
          results:[]

        }

    })

    setTestItems(UploadedItems)

  }

  const runAllTests = () => {

    testCaseRef.current.runAll()
  }


  const clearTestCases = () => {

    // console.log('Clear Test cases')
    setTestItems([])

    if (testItems.length == 0) {
      setTestItems([templateTestItem])

    }

  }


  const extractAllResults =()=>{
    testCaseRef.current.extractAllResults()
  }



  const updateTestResults = useCallback( (result, index) => {

    console.log('Index:', index)

    setTestItems(prevObjs=>(prevObjs.map((item)=>{
      let updatedItem = { ...item, results: result }
      if(item.id==index) return updatedItem
      return item
    })))

  },[])

  return (
    <div style={{ 'backgroundColor': '#1b2829', 'display': 'flex', }} className={styles.dashboard}>
      <Grid>
        <Row stretched style={{}} className={styles.buttonConsole}>

            {<ButtonConsole addTest={addTestItem} addUploadCases={addUploadCases} runAllTests={runAllTests} clearTestCases={clearTestCases} extractAllResults={extractAllResults}  />}
        </Row>

        <Row centered>
          <TestRunStats stats={stats}/>
        </Row>

        <Row style={{ 'display': 'flex', 'flex-direction': 'column' }} ><TestCaseContainer countTestRunStats={countTestRunStats} updateTestResults={updateTestResults} isRun={isRun} ref={testCaseRef} testItems={testItems} /> </Row>
{/* 
        <Row></Row>
        <Row></Row> */}
      </Grid>
    </div>
  );

})

TestContainer. js

const TestCaseContainer = forwardRef((props, ref) => {

  const testCaseRef = useRef([])

  useImperativeHandle(ref, () => ({


    extractAllResults: async () => {


      const data = {
        data:[],
        summary:[]
      }

      testCaseRef.current.forEach(async (item, index) => {

        try {

          const workbook = item.extractAllResults()
          const summary = workbook['summary']

          workbook['data'].forEach(testData => {
            data['data'].push(testData)

          })

          data['summary'].push(summary)



        } catch (err) {
          console.log(err)
        }


      })


      await axios.post('http://localhost:9999/api/downloadresults', data).then(res => {

        console.log('res', res)
        const byteCharacters = atob(res.data);
        const byteNumbers = new Array(byteCharacters.length);
        for (let i = 0; i < byteCharacters.length; i++) {
          byteNumbers[i] = byteCharacters.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        const blob = new Blob([byteArray], { type: 'application/vnd.ms-excel' });
        saveAs(blob, 'TestResults.xlsx')


      })


    },

    runAll: () => {

      testCaseRef.current.forEach(async (item, index) => {
        await item.runAll()

      })
    }


  }));


  const runTestCase = async (date, env, nodeLevel, nodeName, assetClass, metric, dataType, tradeId, testName, key) => {



    let testKey = key

    console.log('FEtCHING', testKey)


    try {

      const params = {
        nodeName,
        date,
        env,
        nodeLevel,
        assetClass,
        metric,
        dataType,
        tradeId,
        testName
      }

      const endpoint ={
        sensitivities:'sensitivities'
      }


      if (metric == 'DELTA_SENSITIVITIES') {
        const result = await axios.get('http://wind08132495.tdbfg.com:9999/api/sensitivities', { params, }).then(response => {

          console.log('response.data', response.data)
          return response.data

        })

        if (result.data == 'none') {

          toast.error(`${date}-${metric}-${nodeName} failed queried! No valutations for trades`, {
            autoClose: 8000,
            position: toast.POSITION.TOP_RIGHT
          });

        } else if (result.data != 'none') {

          // setTestResult(result)
          props.updateTestResults(result, testKey)
          // updateTestResults(false,testKey,'isLoading')


          toast.success(`${date}-${metric}-${nodeName} Successfully queried!`, {
            autoClose: 8000,
            position: toast.POSITION.TOP_RIGHT
          });

        }
        // setTestResult(result.data)
      } else {

        await axios.get(`http://localhost:9999/api/metric/${metric}`, { params, }).then(response => {


          if (response.data != 'none') {

            props.updateTestResults(response.data, testKey)

            toast.success(`${date}-${metric}-${nodeName} Successfully queried!`, {
              autoClose: 8000,
              position: toast.POSITION.TOP_RIGHT
            });


          } else {


            toast.error(`${date}-${metric}-${nodeName} failed queried! No valutations for trades`, {
              autoClose: 8000,
              position: toast.POSITION.TOP_RIGHT
            });


          }

        })

      }

    } catch (error) {

      toast.error(`${date}-${metric}-${nodeName} failed queried! -${error
        }`, {
        autoClose: 8000,
        position: toast.POSITION.TOP_RIGHT
      });

    }

  }


  return (
    <Segment style={{ 'display': 'flex', 'width': 'auto', 'height': '100vh' }} className={styles.testCaseContainer}>
      <div style={{ 'display': 'flex', }}>
      </div>
      <ul style={{overflowY:'auto',height:'100%'}} className='testItemContainer'>
        {

          // memoTestTwo

          // testList
          props.testItems.map((item, index) => {


            let testName
            if (item['formData']['testName'] == '') {
              testName = `testRun-${index}`
            } else {
              testName = item['formData']['testName']
            }

            return <TestCase testResult={item['results']} runTestCase={runTestCase} isRun={props.isRun} ref={el => (testCaseRef.current[index] = el)} testKey={index} key={index} date={item['formData']['date']} env={item['formData']['env']} assetClass={item['formData']['assetClass']} metric={item['formData']['metric']} nodeLevel={item['formData']['nodeLevel']} nodeName={item['formData']['nodeName']} testName={testName} dataType={item['formData']['dataType']} tradeId={item['formData']['tradeId']} hierarchy={hierarchy} />
          })
        }

      </ul>
    </Segment>
  )


})

TestCase. js - отдельный элемент, отображаемый при отображении!

const TestCase = forwardRef((props, ref) => {

    const [isLoading, setIsLoading] = useState(false)
    const inputRefs = useRef()
    const outputRefs = useRef()

    useImperativeHandle(ref, () => ({

      extractAllResults: () => {
        return outputRefs.current.extractAllResults();
      },


      runAll: () => {
        inputRefs.current.runAll()
      },

    }));



    const runSingleTestCase = async (date, env, nodeLevel, nodeName, assetClass, metric, dataType, tradeId, testName, key) => {

      setIsLoading(true)
      await props.runTestCase(date, env, nodeLevel, nodeName, assetClass, metric, dataType, tradeId, testName, key)
      setIsLoading(false)
    }



    const convertDate = (date) => {

      if (date) {
        const newDate = date.split('/')[2] + '-' + date.split('/')[0] + '-' + date.split('/')[1]
        return newDate

      } else {
        return date
      }

    }



    return (
      <Segment color='green' style={{ 'display': 'flex', 'flexDirection': 'column', }}>
        <div style={{ 'display': 'flex', 'justify-content': 'space-between' }}>

          <div style={{ 'display': 'flex', 'height': '30px' }}>
            <Button
              // onClick={props.deleteSingleTest(props.testKey)}

              icon="close"
              inverted
              size="tiny"
              color='red'
            ></Button>

          </div>

          <RegressionInput runSingleTestCase={runSingleTestCase} isRun={props.isRun} testKey={props.testKey} ref={inputRefs} nodeNames={props.hierarchy} runTestCase={props.runTestCase} date={convertDate(props.date)} testName={props.testName} env={props.env} assetClass={props.assetClass} metric={props.metric} nodeLevel={props.nodeLevel} nodeName={props.nodeName} dataType={props.dataType} tradeId={props.tradeId} />

          <TestCheck pass={props.testResult ? props.testResult['CHECK'] : null} />


        </div>

        {
          isLoading ? (<Loading type={'circle'} style={{ 'display': 'flex', 'flexDirecton': 'column', 'justify-content': 'center', 'align-items': 'center', 'marginTop': '50' }} inline />) : (
            <RegressionOutput ref={outputRefs} testName={props.testName} testResult={props.testResult} />
          )
        }

      </Segment>

    )

})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...