简体   繁体   English

React parent 无法更新映射的 JSX 列表中的子组件

[英]React parent couldn't update a child component in a mapped JSX list

NOTE: You can view and edit the code in CodeSandbox .注意:您可以在CodeSandbox中查看和编辑代码。

I have the following parent file which creates a useState list of child component called ProgressBar :我有以下父文件,它创建名为ProgressBar的子组件的useState列表:

import React, { useState } from 'react';
import ProgressBar from './ProgressBar';
import './App.css';

var idCounter = 0;

export default function App() {
  const [barsArray, setBarsArray] = useState([]);
  const [input, setInput] = useState('');

  function add() {
    setBarsArray((prev) => [
      ...prev,
      <ProgressBar key={idCounter++} restart={false} />,
    ]);
  }

  function remove() {
    setBarsArray((prev) => prev.filter((bar) => bar.key !== input));
  }

  function reset() {
    setBarsArray((prev) =>
      prev.map((bar) => (bar.key === input ? { ...bar, restart: true } : bar))
    );
  }

  return (
    <div className='App'>
      <div className='buttons'>
        <button className='button-add' onClick={add}>
          Add
        </button>
        <button className='button-delete' onClick={remove}>
          Delete
        </button>
        <button className='button-delete' onClick={reset}>
          Reset
        </button>
        <input
          type='number'
          value={input}
          onInput={(e) => setInput(e.target.value)}
        />
      </div>
      <div className='bars-container'>
        {barsArray.map((bar) => (
          <div className='bars-index' key={bar.key}>
            {bar}
            <p>{bar.key}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

The file of the child ProgressBar has the following content:ProgressBar的文件有以下内容:

import React, { useEffect, useState } from 'react';
import './ProgressBar.css';

export default function ProgressBar(props) {
  const [progress, setProgress] = useState(0);

  let interval;

  useEffect(() => {
    interval = setInterval(() => {
      setProgress((prev) => prev + 1);
    }, RnadInt(10, 120));
  }, []);

  useEffect(() => {
    if (progress >= 100) clearInterval(interval);
  }, [progress]);

  if (props.restart === true) {
    setProgress(0);
  }
  return (
    <>
      <div className='ProgressBarContainer'>
        <div className='ProgressBar' style={{ width: progress + '%' }}></div>
      </div>
    </>
  );
}

function RnadInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

My problem is that the reset button in the parent doesn't work, as far as I'm concerned, if you change the passed props to the child, the child automatically re-renders, but even though I'm updating the props in reset function in the parent, which maps the old array of child components to a new array and only changes the props of the selected child.我的问题是父母中的重置按钮不起作用,就我而言,如果您将传递的道具更改为孩子,孩子会自动重新渲染,但即使我正在更新道具在 parent 中reset function,它将子组件的旧数组映射到新数组,并且只更改所选子组件的 props。

Thanks谢谢

Adding the element in state via add would require to keep the ref of element instead of actual prop bind to element.通过add在 state 中添加元素需要保留元素的引用而不是实际的道具绑定到元素。 Suggestion here to use the model object and while rendering use the JSX element.此处建议使用 model object 并在渲染时使用 JSX 元素。

Please use the below code which defines the barsArray as object state and later uses it render ProgressBar component (from map call).请使用下面的代码将barsArray定义为 object state 并稍后使用它渲染ProgressBar组件(来自 map 调用)。

Check the working codesandbox - https://codesandbox.io/s/admiring-glitter-j3b7sw?file=/src/App.js:0-1446检查工作代码框 - https://codesandbox.io/s/admiring-glitter-j3b7sw?file=/src/App.js:0-1446

import React, { useState } from "react";
import ProgressBar from "./ProgressBar";
import "./App.css";

var idCounter = 0;

export default function App() {
  const [barsArray, setBarsArray] = useState([]);
  const [input, setInput] = useState("");

  function add() {
    setBarsArray((prev) => [...prev, { id: idCounter++, restart: false }]);
  }

  function remove() {
    setBarsArray((prev) =>
      prev.filter((bar) => bar.id.toString() !== input.toString())
    );
  }

  function reset() {
    setBarsArray((prev) =>
      prev.map((bar) => {
        return bar.id.toString() === input.toString()
          ? { ...bar, restart: true }
          : { ...bar };
      })
    );
  }

  return (
    <div className="App">
      <div className="buttons">
        <button className="button-add" onClick={add}>
          Add
        </button>
        <button className="button-delete" onClick={remove}>
          Delete
        </button>
        <button className="button-delete" onClick={reset}>
          Reset
        </button>
        <input
          type="number"
          value={input}
          onInput={(e) => setInput(e.target.value)}
        />
      </div>
      <div className="bars-container">
        {barsArray.map((bar) => (
          <div className="bars-index" key={bar.id}>
            <ProgressBar key={bar.id} restart={bar.restart} />
            <p>{bar.key}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

This simple fix worked for me, in the file of the child, call the conditional expression in a useEffect hook.这个简单的修复对我有用,在孩子的文件中,在 useEffect 挂钩中调用条件表达式。 Currently, it doesn't listen to the changes in props.restart and only runs on the initial render.目前,它不监听 props.restart 的变化,只在初始渲染时运行。

check https://reactjs.org/docs/hooks-reference.html#useeffect检查https://reactjs.org/docs/hooks-reference.html#useeffect

 useEffect(() => {
    if (props.restart === true) {
      setProgress(0);
    }
  }, [props.restart])

link to working codesandbox https://codesandbox.io/s/distracted-gauss-24d0pu链接到工作代码和框https://codesandbox.io/s/distracted-gauss-24d0pu

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

相关问题 在React中将状态从子组件更新为父组件 - Update the state from child to parent component in React React:更新子组件而不重新渲染父组件 - React: Update Child Component Without Rerendering Parent 当提供程序组件父状态更改时,为什么无法更新子组件中的值(使用react上下文)? - Why can't update a value in a child component (with react context) when a provider component parent state change? 无法从 React Native 中的父组件更新子组件的属性 - Can’t update the property of a child component from a parent component in React Native 子组件无法通过父组件中的 state 更新正确更新 - Child component doesn't update correctly with state update in parent component React/Redux - 从子组件更新父组件中的状态 - React/Redux - Update state in parent component from child component 当子组件更改数据库时,对父组件进行更新 - React parent component update when child component alters database 当父组件更新时,React阻止子组件中的更改状态 - React prevent change state in child component when parent component update 从父组件更新子组件道具反应原生 - Update child component props from Parent component react native 在 React 的父组件上使用过滤器时更新子组件 - Update child component while using filter on parent component in React
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM