Почему бы не использовать command.getoutput () вместо?
import commands
text = "Mario Balotelli"
output = 'espeak "%s"' % text
print text
a = commands.getoutput(output)
В вашем сценарии вам вообще не нужно использовать или повторно внедрять getDerivedStateFromProps
. Вам просто нужно создать новую переменную, чтобы получить новую форму данных. Использование состояния в этом сценарии вызовет еще один повторный рендеринг, который не является хорошим с точки зрения производительности.
import React from 'react';
const App = ({ count }) => {
const derivedCount = count > 100 ? 100 : count;
return (
<div>Counter: {derivedCount}</div>
);
}
App.propTypes = {
count: PropTypes.number.isRequired
}
Демонстрация здесь: https://codesandbox.io/embed/qzn8y9y24j?fontsize=14
Подробнее о различных способах решения подобных сценариев можно прочитать без используя getDerivedStateFromProps
здесь: https://reactjs.org/blog/2018/06/07/you-probbly-dont-need-derived-state.html
Если вы действительно нужно использовать отдельное состояние, вы можете использовать что-то подобное
import React, { useState } from 'react';
const App = ({ count }) => {
const [derivedCounter, setDerivedCounter] = useState(
count > 100 ? 100 : count
);
useEffect(() => {
setDerivedCounter(count > 100 ? 100 : count);
}, [count]); // this line will tell react only trigger if count was changed
return <div>Counter: {derivedCounter}</div>;
};
Я понимаю, что ваш пример «производного состояния» преднамеренно прост, но поскольку существует очень мало законных случаев производного состояния, трудно дать рекомендацию о замене, кроме как в каждом конкретном случае, поскольку он зависит от причина, по которой вы используете производное состояние. В приведенном вами конкретном примере не было никакой причины использовать производное состояние в случае класса, и поэтому в случае ловушки по-прежнему нет никаких причин (значение может быть просто получено локально, не переводя его в состояние). Если полученное значение дорого, вы можете использовать useMemo
, как представляет Tholle. Если они не соответствуют более реалистичным случаям, которые вы имеете в виду, вам нужно представить более конкретный случай, который действительно требует производного состояния.
Насколько ваш пример componentDidUpdate
, если то, что вы хотите сделать для разных реквизитов, является независимым, то вы можете использовать отдельные эффекты для каждого (то есть, несколько useEffect
вызовов). Если вы хотите сделать точно , как в вашем примере (т.е. сделать что-то только для изменения companyName
, если groupName
также не изменилось, как указано вашим else if
), тогда вы можете использовать ссылки для более сложных условий. Вы не должны не изменять мутировку ref во время рендеринга (всегда существует вероятность того, что рендер будет отброшен / переделан, если поддерживается параллельный режим), поэтому в примере используется последний эффект для обновления ссылок. В моем примере я использую ссылку, чтобы не выполнять эффектную работу на начальном рендере (см. Ответ Толле в на этот связанный вопрос ) и чтобы определить, изменился ли groupName
при принятии решения о том, выполнять работу или нет. на основе изменения companyName
.
const { useState, useEffect, useRef } = React;
const DerivedStateFromProps = ({ count }) => {
const derivedCount = count > 100 ? 100 : count;
return (
<div>
Derived from {count}: {derivedCount}{" "}
</div>
);
};
const ComponentDidUpdate = ({ groupName, companyName }) => {
const initialRender = useRef(true);
const lastGroupName = useRef(groupName);
useEffect(
() => {
if (!initialRender.current) {
console.log("Do something when groupName changes", groupName);
}
},
[groupName]
);
useEffect(
() => {
if (!initialRender.current) {
console.log("Do something when companyName changes", companyName);
}
},
[companyName]
);
useEffect(
() => {
if (!initialRender.current && groupName === lastGroupName.current)
console.log(
"Do something when companyName changes only if groupName didn't also change",
companyName
);
},
[companyName]
);
useEffect(
() => {
// This effect is last so that these refs can be read accurately in all the other effects.
initialRender.current = false;
lastGroupName.current = groupName;
},
[groupName]
);
return null;
};
function App() {
const [count, setCount] = useState(98);
const [groupName, setGroupName] = useState("initial groupName");
const [companyName, setCompanyName] = useState("initial companyName");
return (
<div>
<div>
<DerivedStateFromProps count={count} />
<button onClick={() => setCount(prevCount => prevCount + 1)}>
Increment Count
</button>
</div>
<div>
<ComponentDidUpdate groupName={groupName} companyName={companyName} />
groupName:{" "}
<input
type="text"
value={groupName}
onChange={event => setGroupName(event.target.value)}
/>
<br />
companyName:{" "}
<input
type="text"
value={companyName}
onChange={event => setCompanyName(event.target.value)}
/>
<br />
change both{" "}
<input
type="text"
onChange={event => {
const suffix = event.target.value;
setGroupName(prev => prev + suffix);
setCompanyName(prev => prev + suffix);
}}
/>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>