首先,我的方法可能从一开始就被误导。
我有一个组件列出了兄弟组件添加的对象。
我希望列表组件在添加新对象时更新。
如您所见,我在两个组件中调用相同的函数(getHostedServiceList)。显然,这需要清理,但我想让它先工作
我正在使用钩子来实现这一目标。
//输入
const options = [
{ value: '1', label: '1' },
{ value: '2', label: '2' },
{ value: '3', label: '3' },
];
// class Remotes extends Component {
const Remotes = ({ ...props }) => {
const [service, setService] = useState();
const [url, setUrl] = useState();
const [token, setToken] = useState();
const [displayName, setDisplayName] = useState();
const [apiUrl, setApiUrl] = useState();
const [services, setServices] = useState();
let HOME = process.env.HOME || '';
if (process.platform === 'win32') {
HOME = process.env.USERPROFILE || '';
}
const getHostedServiceList = () => {
console.log('props', props);
if (!fs.existsSync(`${HOME}/providers.json`)) {
return newMessage(
`Unable to locate ${HOME}/providers.json`,
'error',
);
}
const payload = JSON.parse(
fs.readFileSync(`${HOME}/providers.json`),
);
setServices(payload);
};
const setProvider = selectedOption => {
setService(selectedOption.value);
setUrl(`http://www.${selectedOption.value}.com`);
setApiUrl(`http://www.${selectedOption.value}.com/api/v1`);
};
const { onAddRemote } = props;
return (
<div>
<div>Add a remote host:</div>
<StyledSelect
value="Select Provider"
onChange={setProvider}
options={options}
/>
{console.log('service', service)}
<TextInput
label="Url"
defaultValue={url}
onChange={e => {
setProvider(e.target.value);
}}
disabled={!service ? 'disabled' : ''}
/>
<TextInput
label="API Url"
defaultValue={apiUrl}
onChange={e => setApiUrl(e.target.value)}
disabled={!service ? 'disabled' : ''}
/>
<TextInput
label="Token"
onChange={e => setToken(e.target.value)}
disabled={!service ? 'disabled' : ''}
/>
<TextInput
label="Display Name"
onChange={e => setDisplayName(e.target.value)}
disabled={!service ? 'disabled' : ''}
/>
<Button
disabled={!service || !url || !token}
onClick={() => {
onAddRemote({ service, url, apiUrl, token, displayName });
getHostedServiceList();
}}
>
Add Remote
</Button>
</div>
);
};
//列表
const HostedProviderList = ({ ...props }) => {
const [services, setServices] = useState();
let HOME = process.env.HOME || '';
if (process.platform === 'win32') {
HOME = process.env.USERPROFILE || '';
}
const getHostedServiceList = () => {
console.log('props', props);
if (!fs.existsSync(`${HOME}/providers.json`)) {
return newMessage(
`Unable to locate ${HOME}/providers.json`,
'error',
);
}
const payload = JSON.parse(
fs.readFileSync(`${HOME}/providers.json`),
);
setServices(payload);
};
useEffect(() => {
// console.log('props 1', services);
getHostedServiceList();
}, []);
return (
<Wrapper>
<Flexbox>
<Title>Provider List</Title>
</Flexbox>
<div>
{services &&
services.map((service, i) => (
<Service key={i}>
<ServiceName>{service.displayName}</ServiceName>
<ServiceProvider>{service.service}</ServiceProvider>
</Service>
))}
</div>
</Wrapper>
);
};
我希望列表组件在添加新对象时更新。
是的,您可以使用Redux(或React自己的“上下文”)进行全局状态处理。但是,一个更简单的解决方案可能只是将数据发送到父级并传递给列表组件,如下所示:
class Parent extends Component {
state = { objectsAdded: [] }
onObjectAdded = ( obj ) => {
// deepclone may be needed
this.setState({objectsAdded: this.state.objectsAdded.concat(obj)})
}
render() {
return (
<Fragment>
<ListComponent objects={this.state.objectsAdded} />
<ObjectAdder onObjectAdded={this.onObjectAdded} />
</Fragment>
}
}
这就像Redux或MobX这样的东西派上用场。这些工具允许您创建“商店” - 您在整个应用中加载和存储不同组件使用的数据的位置。然后,将商店连接到与数据交互的各个组件(显示列表,显示创建/编辑表单等)。每当一个组件修改数据时,所有其他组件将自动接收更新。
实现这种交叉通信的一种方式是通过pub/sub机制 - 只要一个组件创建或修改数据,它就会发布(或“发送”)一个事件。其他组件为这些事件订阅(或“监听”)并相应地做出反应(或“重新呈现”)。我将研究和实现留给读者,因为它无法在StackOverflow答案中快速汇总。
您也可以尝试使用新的React hooks,因为这样可以轻松地在组件之间共享数据。如果您选择此选项,请特别注意正确操作,因为它很容易变得懒惰和不负责任。
为了帮助您入门,这里有一些要阅读的文章。我强烈建议您阅读第一篇: