如何在 React Hooks 中将道具更改为状态?
How to change props to state in React Hooks?
在 Simple react class 组件中,我们曾经将 props 更改为这样的状态:
constructor(props) {
super(props)
this.state = {
pitch: props.booking.pitch,
email: props.booking.email,
firstName: props.booking.firstName,
arrivalDate: props.booking.arrivalDate
}
}
但是我不知道如何在 Hooks 的新功能中做到这一点,但我正在尝试这样做。
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(null)
useEffect(() => {
setDescription(initialDesc)
}, {})
function handleChangeVariance(newVariance) {
setDescription({
...description,
template: {
...description.template,
variance_name: newVariance,
},
})
}
}
基本上,我只需要将来自另一个父组件的描述道具更改为状态即可。请问,你能告诉我如何用 Hooks 方式以新的方式做到这一点吗?
您可以像这样将初始状态作为第一个参数传递给 useState
:
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(initialDesc)
...
您的状态的初始值是传入 useState
的值:
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(initialDesc)
如 documentation 所述:
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
相当于:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
您的代码中的问题出在 {}
。
UseEffect 挂钩期望和数组,而不是对象。请改用 [initialDesc]
。
这是在 props 改变时重置组件状态的方式
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(null)
useEffect(() => {
setDescription(initialDesc)
}, [initialDesc]);
}
这就是您如何将组件状态初始化为仅在第一次渲染时的 prop 值
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(initialDesc);
}
很难实现依赖于 prop 值的状态,同时避免不必要的重新渲染。
这是我创建这样一个钩子的尝试:
/**
* Replacement for useState which depends on prop value and avoids unnecessary re-renders.
*/
export function useStateBasedOnProps(propValue) {
const [, update] = useState(false);
const [state, setState] = useMemo(() => {
const state = {};
return [
state,
(value) => {
if (value instanceof Function) {
state.value = value(state.value);
} else {
state.value = value;
}
update((tick) => !tick);
}
];
}, [update]);
if (state.prevPropValue !== propValue) {
state.prevPropValue = propValue;
state.value = propValue;
}
return [state.value, setState];
}
这是一个用法示例:
function IncButton({initialValue}) {
const [value, setValue] = useStateBasedOnProps(initialValue);
const increment = useCallback(() => setValue((prev) => prev + 1), [setValue]);
return <button onClick={increment}>Click to increment: {value}</button>;
}
完整示例:https://gist.github.com/mdevils/b861610780300784292194f65886517a
在 Simple react class 组件中,我们曾经将 props 更改为这样的状态:
constructor(props) {
super(props)
this.state = {
pitch: props.booking.pitch,
email: props.booking.email,
firstName: props.booking.firstName,
arrivalDate: props.booking.arrivalDate
}
}
但是我不知道如何在 Hooks 的新功能中做到这一点,但我正在尝试这样做。
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(null)
useEffect(() => {
setDescription(initialDesc)
}, {})
function handleChangeVariance(newVariance) {
setDescription({
...description,
template: {
...description.template,
variance_name: newVariance,
},
})
}
}
基本上,我只需要将来自另一个父组件的描述道具更改为状态即可。请问,你能告诉我如何用 Hooks 方式以新的方式做到这一点吗?
您可以像这样将初始状态作为第一个参数传递给 useState
:
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(initialDesc)
...
您的状态的初始值是传入 useState
的值:
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(initialDesc)
如 documentation 所述:
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
相当于:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
您的代码中的问题出在 {}
。
UseEffect 挂钩期望和数组,而不是对象。请改用 [initialDesc]
。
这是在 props 改变时重置组件状态的方式
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(null)
useEffect(() => {
setDescription(initialDesc)
}, [initialDesc]);
}
这就是您如何将组件状态初始化为仅在第一次渲染时的 prop 值
const GenerateDescHook = ({ description: initialDesc }) => {
const [description, setDescription] = useState(initialDesc);
}
很难实现依赖于 prop 值的状态,同时避免不必要的重新渲染。
这是我创建这样一个钩子的尝试:
/**
* Replacement for useState which depends on prop value and avoids unnecessary re-renders.
*/
export function useStateBasedOnProps(propValue) {
const [, update] = useState(false);
const [state, setState] = useMemo(() => {
const state = {};
return [
state,
(value) => {
if (value instanceof Function) {
state.value = value(state.value);
} else {
state.value = value;
}
update((tick) => !tick);
}
];
}, [update]);
if (state.prevPropValue !== propValue) {
state.prevPropValue = propValue;
state.value = propValue;
}
return [state.value, setState];
}
这是一个用法示例:
function IncButton({initialValue}) {
const [value, setValue] = useStateBasedOnProps(initialValue);
const increment = useCallback(() => setValue((prev) => prev + 1), [setValue]);
return <button onClick={increment}>Click to increment: {value}</button>;
}
完整示例:https://gist.github.com/mdevils/b861610780300784292194f65886517a