我想将两个状态作为设置组件中的getSettings方法的结果传递给Add组件.如果不将方法复制到其他组件,有没有办法做到这一点?
谢谢
设置组件
export class Settings extends Component {
constructor(props) {
super(props);
this.state = {
languages: [],
currencies: []
};
}
getSettings() {
fetch('/settings', {
method: 'get',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then( ... )
.then(json => {
this.setState({
currencies: json.currencies,
languages: json.languages
});
})
}
}
Run Code Online (Sandbox Code Playgroud)
添加组件
export class Add extends Component {
displayName = Add.name
constructor(props) {
super(props);
this.state = {
languages: [],
currencies: []
};
}
Run Code Online (Sandbox Code Playgroud)
我可以想到两种方式,你可以分享你的状态Settings.
你可以简单地将状态传递给this.props.children或this.props.render.
class Settings extends Component {
state = {
languages: [],
currencies: []
};
getSettings = () => {
// fetch('/settings', {
// method: 'get',
// headers: {
// 'Accept': 'application/json',
// 'Content-Type': 'application/json'
// }
// })
// .then( ... )
// .then(json => {
// this.setState({
// currencies: json.currencies,
// languages: json.languages
// });
// })
this.setState({
currencies: ["Dollar", "Euro", "Won"],
languages: ["English", "French", "Korean"]
});
};
componentDidMount() {
this.getSettings();
}
render() {
return <div>{this.props.children(this.state)}</div>;
}
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它.
const renderComponents = (currencies, languages) => {
const currencyItems = currencies.map(currency => (
<li key={currency}>{currency}</li>
));
const languageItems = languages.map(language => (
<li key={language}>{language}</li>
));
return (
<div>
<h3>currencies</h3>
<ul>{currencyItems}</ul>
<hr />
<h3>languages</h3>
<ul>{languageItems}</ul>
</div>
);
};
const AppChildAsFunction = () => (
<div>
<h2>Using Child as Function</h2>
<Settings>
{({ currencies, languages }) => renderComponents(currencies, languages)}
</Settings>
</div>
);
Run Code Online (Sandbox Code Playgroud)
创建和导出新的设置提供程序和使用者
SettingsContext.js
import React, { Component } from "react";
const defaultValue = {
currencies: ["Dollar", "Euro", "Won"],
languages: ["English", "French", "Korean"]
};
const { Provider, Consumer: SettingsConsumer } = React.createContext(
defaultValue
);
class SettingsProvider extends Component {
state = {
languages: [],
currencies: []
};
render() {
return <Provider value={this.state}>{this.props.children}</Provider>;
}
}
export { SettingsProvider, SettingsConsumer };
Run Code Online (Sandbox Code Playgroud)
用法大致相同
App.js
import { SettingsProvider, SettingsConsumer } from "./SettingsContext";
...
const AppWithContext = () => (
<div>
<h2>Using Context API</h2>
<SettingsConsumer>
{({ currencies, languages }) => renderComponents(currencies, languages)}
</SettingsConsumer>
</div>
);
Run Code Online (Sandbox Code Playgroud)
您可以选择适合您口味的任何一种.
小智 2
请原谅我慷慨激昂的恳求,但出于对所有神圣事物的热爱,请不要使用高阶组件抽象、渲染道具等。这是一个简单的问题,值得一个简单的解决方案。不需要魔法。不需要深奥的 React 知识。
恭喜,您现在拥有一个可重用且可独立测试的函数,任何组件(或任何其他相关组件)都可以根据需要使用该函数。
const getSettings = component => () => {
// Do your fetch here, and in your last
// .then(), just use 'component.setState'
// instead of 'this.setState'
// Simulate async
setTimeout(() => {
component.setState({
name: component.name,
currencies: "whatever",
languages: "yep"
});
}, 1000);
};
export default getSettings;
Run Code Online (Sandbox Code Playgroud)就这么简单。
请参阅https://codesandbox.io/s/mjmpw5k08y
事后看来,您可能可以接受回调函数而不是组件,或者返回一个承诺。其中任何一个都会减少它与 React 组件的耦合。未经测试的代码如下...
const getSettings = callback => {
// Simulate async
setTimeout(() => {
callback({
name: component.name,
currencies: "whatever",
languages: "yep"
});
}, 1000);
};
Run Code Online (Sandbox Code Playgroud)
用法
getSettings(this.setState.bind(this));
Run Code Online (Sandbox Code Playgroud)
const getSettings = () => window.fetch
.then(res => res.json());
Run Code Online (Sandbox Code Playgroud)
用法
getSettings().then(this.setState.bind(this));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
110 次 |
| 最近记录: |