reactjs 如何使用新的道具重新呈现React功能组件?

9gm1akwq  于 2022-11-22  发布在  React
关注(0)|答案(7)|浏览(199)

bounty已结束。回答此问题可获得+100声望奖励。奖励宽限期将在20小时后结束。Adam Zerner希望吸引更多人关注此问题。

我想做这样的事情:

const GreetingWithCounter = (props) => {
  const { name, count } = props;

  return (
    <div>
      <div>Hello {name}</div>
      <button onClick={() => render({ ...props, count: count + 1 })}>
        {count}
      </button>
    </div>
  );
}

<GreetingWithCounter name="Alice" count={0} />

我想重新渲染一个组件,但不想为它的props设置新的值。有办法吗?通过这三个问题,我找到了重新渲染一个组件的方法,但不想为props(1,2,3)设置新的值。

内容

我正在考虑一种简化React的方法。我真的很喜欢将React作为MVC中的视图层的心理模型,其中UI = F(state)。但是当“state”来自如此多不同的地方时,事情会变得混乱:propsuseStateuseReducer、“原始”useContext、Redux(我认为它使用useContext),以及其他内容。
如果一切都是基于道具呢?

  • 对于本地状态,你可以做我在上面的例子中做的。你可以在执行<GreetingWithCounter name="Alice" count={0} />时初始化count的本地状态,然后通过重新渲染来更新它。这意味着更少的干燥,因为你必须重复count={0}代码,而不是在GreetingWithCounter中只使用一次。
  • 你必须做支柱钻孔,而不是useContext的东西。
  • 这种方法可能会使React变慢。
  • 尽管如此,我还是假设:1)从道具中获得一切的心理模型更简单; 2)在大量的应用程序中,优点大于缺点。
xmq68pz9

xmq68pz91#

道具不应该在React中发生变化。这正是道具和状态之间的区别。React实现这一点的方法是使用状态作为计数。您可以将计数的初始状态作为道具传递,并执行以下操作:const [count, setCount] = useState(initialCount)。您的onClick处理程序将递增count,这也是state。我知道这不是您想要的,但这是React的工作方式。

laximzn5

laximzn52#

在React Props中,无法在子组件中更改值,但可以在父组件中进行更改。

const GreetingWithCounter = (props) => {
  const { name, count, updateCount } = props;

  return (
    <div>
      <div>Hello {name}</div>
      <button onClick={updateCount}>{count}</button>
    </div>
  );
};

function App() {
  const [count, setCount] = useState(0);

  const updateCount = () => {
    setCount(count + 1);
  };

  return (
    <div className='App'>
      <h1>Greeting With Counter:</h1>
      <GreetingWithCounter
        name='Alice'
        count={count}
        updateCount={updateCount}
      />
    </div>
  );
}
xj3cbfub

xj3cbfub3#

感谢您想要指出的变化和您想要添加的价值,但可能有一些点,您错过了什么React在概念上试图提供propsstate之间的分离。

  • React附带的组件中的道具在概念上被专门设计为不可变的,正如本文中的文档所示。*

因此,你试图做的事情在概念上不适合这个目的,并且违反了React试图完成的目标。
事实上,你可能会提到创建另一个库/框架,在引入**props are the new state**概念时成功地完成了它,但在这个特定的例子中,没有可能的方法以React的方式成功。

j2datikz

j2datikz4#

你不能改变子组件中的props值,但你有两种方法来处理它,我假设你只想在子组件中使用count,而不需要父组件中的count值,在这种情况下,你可以使用props.count作为初始状态,类似如下:

const GreetingWithCounter = props => {
  const [count, setCount] = useState(props.count);
  const { name } = props;

  return (
    <div>
      <div>Hello {name}</div>
      <button onClick={() => setCount(prevState => prevState + 1)}>{count}</button>
    </div>
  );
};

<GreetingWithCounter name="Alice" count={0} />;

但如果要从父级访问它的值,最好将setter传递给子级
这样的东西:

const GreetingWithCounter = ({name,count,setCount}) => {
  

  return (
    <div>
      <div>Hello {name}</div>
      <button onClick={() => setCount(prevState => prevState + 1)}>{count}</button>
    </div>
  );
};

const App = ()=>{
  const [count, setCount] = useState(0);
  return (<GreetingWithCounter name="Alice" count={count} setCount={setCount} />)
}

或者如果它的子节点太深,需要向它的所有树发送道具,最好使用状态管理,如Redux、Context或...

lsmepo6l

lsmepo6l5#

这是你想要的方式吗?:

import React from 'react'
import ReactDOM from 'react-dom'

export default function renderComponent(Component, props, container) {
    ReactDOM.render(<Component {...props} />, container)
}
crcmnpdw

crcmnpdw6#

你想做的事情违背了国家管理的React哲学。正确的方法,你可以检查其他答案,甚至你自己已经张贴在问题。
但是如果你真的想这么做,在它的魔力背后,React也只是JavaScript。因此,我们只需要在React思维方式之外实现render函数。我们知道React在状态改变魔力或属性改变时重新呈现。我们只需要以某种方式将你要求的render方法与set state连接起来。类似下面的东西应该可以工作。

const ParentStuff = () => {
    const [props, setProps] = useState({ name: "Alice", count: 0 });
    render = setProps;

    return (<GreetingWithCounter name={props.name} count={props.count} />);
}

let render;

const GreetingWithCounter = props => {
  const { name, count } = props;

  return (
    <div>
      <div>Hello {name}</div>
      <button onClick={() => render({ ...props, count: count + 1 })}>{count}</button>
    </div>
  );
};

很多人会对上面的代码尖叫,它肯定偏离了预期的用途。
如果你想更进一步,你也可以只为整个应用程序设置一个状态,并将此状态传递给每个组件。瞧!你刚刚创建了一个单例状态和一个单向数据流,这是一个糟糕的redux版本,这可能会降低Web应用程序的性能,因为在文本框中键入每个字母等操作将重新呈现整个页面。

67up9zun

67up9zun7#

正如其他人已经提到的,组分在React中是受控的或不受控的(或两者的混合)。
如果你把状态保留在组件本身-它是不受控制的。你可以通过改变key属性从父组件重置它的状态到内部。
如果您将状态保留在父级中-它是受控组件,并通过属性/回调更改其状态。
你在你的例子中所展示的,你想用一些语法糖来实现不受控制的组件。
实施示例:

const usePropsWithRender = (props) => {
  const [currentProps, setCurrentProps] = useState(props);
  return {
    ...currentProps,
    render: setCurrentProps,
  };
};

const GreetingWithCounter = (props) => {
  const { name, count, render } = usePropsWithRender(props);

  return (
    <div>
      <div>Hello {name}</div>
      <button onClick={() => render({ ...props, count: count + 1 })}>
        {count}
      </button>
    </div>
  );
};

您可以在整个项目中重用usePropsWithRender,但它只不过是useState的一个简单的 Package 器,我看不出它比直接使用useState有什么好处。

相关问题